AVDVirglRenderer: Host-side 3D for cuttlefish

Initial implementation of libvirglrenderer for the cuttlefish AVD.

This replaces the host renderer part of the Virgil3D project. Control
messages are replaced with the goldfish-opengl protocol. QEMU needs to
be built with support for libvirglrenderer, then this library can either
replace the system copy of libvirglrenderer, or be LD_PRELOADed.

Code from the goldfish emulator has been extensively reused. The
protocol decoders are identical to those used by the external/qemu
emu-master-dev project. Additionally, the OpenGLESDispatch library
was taken and repurposed to allow an alternative EGL/GLES implementation
to be loaded and utilized by AVDVirglRenderer.

- OpenGL ES 1.1 and OpenGL ES 3.1 are supported.
- OpenGL ES 3.2 support is not planned.
- Vulkan support is not planned.

Bug: 77276633
Change-Id: I981102308113577bccb514d1d7c515a999e6b059
diff --git a/android/emulation/DmaMap.cpp b/android/emulation/DmaMap.cpp
deleted file mode 100644
index fb04803..0000000
--- a/android/emulation/DmaMap.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-// 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 "android/emulation/DmaMap.h"
-
-#include "android/base/containers/Lookup.h"
-#include "android/base/memory/LazyInstance.h"
-
-#include <type_traits>
-#include <inttypes.h>
-#include <stdio.h>
-
-#define DEBUG 0
-
-#if DEBUG >= 1
-#define D(fmt,...) fprintf(stderr, "DmaMap: %s: " fmt "\n", __func__, ##__VA_ARGS__);
-#else
-#define D(...) (void)0
-#endif
-
-#if DEBUG >= 2
-#define DD(fmt,...) fprintf(stderr, "DmaMap: %s: " fmt "\n", __func__, ##__VA_ARGS__);
-#else
-#define DD(...) (void)0
-#endif
-
-#define E(fmt,...) fprintf(stderr, "DmaMap: ERROR: %s: " fmt "\n", __func__, ##__VA_ARGS__);
-
-namespace android {
-
-static DmaMap* sInstance = nullptr;
-
-DmaMap* DmaMap::get() {
-    return sInstance;
-}
-
-DmaMap* DmaMap::set(DmaMap* dmaMap) {
-    DmaMap* result = sInstance;
-    sInstance = dmaMap;
-    return result;
-}
-
-void DmaMap::addBuffer(void* hwpipe,
-                       uint64_t guest_paddr,
-                       uint64_t bufferSize) {
-    D("guest paddr 0x%llx bufferSize %llu",
-      (unsigned long long)guest_paddr,
-      (unsigned long long)bufferSize);
-    DmaBufferInfo info;
-    info.hwpipe = hwpipe;
-    info.guestAddr = guest_paddr; // guest address
-    info.bufferSize = bufferSize; // size of buffer
-    info.currHostAddr = kNullopt; // no current host address
-    android::base::AutoWriteLock lock(mLock);
-    createMappingLocked(&info);
-    mDmaBuffers[guest_paddr] = info;
-}
-
-void DmaMap::removeBuffer(uint64_t guest_paddr) {
-    D("guest paddr 0x%llx", (unsigned long long)guest_paddr);
-    android::base::AutoWriteLock lock(mLock);
-    if (auto info = android::base::find(mDmaBuffers, guest_paddr)) {
-        removeMappingLocked(info);
-        mDmaBuffers.erase(guest_paddr);
-    } else {
-        E("guest addr 0x%llx not alloced!",
-          (unsigned long long)guest_paddr);
-    }
-}
-
-void* DmaMap::getHostAddr(uint64_t guest_paddr) {
-    DD("guest paddr 0x%llx", (unsigned long long)guest_paddr);
-    android::base::AutoReadLock rlock(mLock);
-    if (auto info = android::base::find(mDmaBuffers, guest_paddr)) {
-        if (info->currHostAddr) {
-            DD("guest paddr 0x%llx -> host 0x%llx valid",
-              (unsigned long long)guest_paddr,
-              (unsigned long long)(*info->currHostAddr));
-            return *(info->currHostAddr);
-        } else {
-            rlock.unlockRead();
-            android::base::AutoWriteLock wlock(mLock);
-            createMappingLocked(info);
-            D("guest paddr 0x%llx -> host 0x%llx valid (new)",
-              (unsigned long long)guest_paddr,
-              (unsigned long long)*(info->currHostAddr));
-            return *(info->currHostAddr);
-        }
-    } else {
-        E("guest paddr 0x%llx not alloced!",
-          (unsigned long long)guest_paddr);
-        return 0;
-    }
-}
-
-void DmaMap::invalidateHostMappings() {
-    android::base::AutoWriteLock lock(mLock);
-    for (auto& it : mDmaBuffers) {
-        removeMappingLocked(&it.second);
-    }
-}
-
-void DmaMap::resetHostMappings() {
-    android::base::AutoWriteLock lock(mLock);
-    for (auto& it : mDmaBuffers) {
-        removeMappingLocked(&it.second);
-    }
-    mDmaBuffers.clear();
-}
-
-void* DmaMap::getPipeInstance(uint64_t guest_paddr) {
-    android::base::AutoReadLock lock(mLock);
-    if (auto info = android::base::find(mDmaBuffers, guest_paddr)) {
-        return info->hwpipe;
-    } else {
-        E("guest paddr 0x%llx not alloced!",
-          (unsigned long long)guest_paddr);
-        return nullptr;
-    }
-}
-
-void DmaMap::createMappingLocked(DmaBufferInfo* info) {
-    info->currHostAddr = doMap(info->guestAddr, info->bufferSize);
-}
-
-void DmaMap::removeMappingLocked(DmaBufferInfo* info ) {
-    if (info->currHostAddr) {
-        doUnmap(*(info->currHostAddr), info->bufferSize);
-        info->currHostAddr = kNullopt;
-        D("guest addr 0x%llx host mapping 0x%llx removed.",
-          (unsigned long long)info->guestAddr,
-          (unsigned long long)info->currHostAddr);
-    } else {
-        D("guest addr 0x%llx has no host mapping. don't remove.",
-          (unsigned long long)info->guestAddr);
-    }
-}
-
-}  // namespace android
-
-
diff --git a/android/emulation/DmaMap.h b/android/emulation/DmaMap.h
deleted file mode 100644
index 754549f..0000000
--- a/android/emulation/DmaMap.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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.
-
-#pragma once
-
-#include "android/base/Compiler.h"
-#include "android/base/Optional.h"
-#include "android/base/synchronization/Lock.h"
-
-#include <unordered_map>
-#include <inttypes.h>
-
-using android::base::Optional;
-using android::base::kNullopt;
-
-namespace android {
-
-struct DmaBufferInfo {
-    void* hwpipe = nullptr;
-    uint64_t guestAddr = 0;
-    uint64_t bufferSize = 0;
-    Optional<void*> currHostAddr = kNullopt;
-};
-
-class DmaMap {
-public:
-    // Constructor.
-    DmaMap() = default;
-
-    // Destructor.
-    virtual ~DmaMap() = default;
-
-    void addBuffer(void* hwpipe, uint64_t addr, uint64_t bufferSize);
-    void removeBuffer(uint64_t addr);
-    void* getHostAddr(uint64_t addr);
-    void invalidateHostMappings();
-    void resetHostMappings();
-    void* getPipeInstance(uint64_t addr);
-
-    // get() / set are NOT thread-safe,
-    // but we don't expect multiple threads to call this
-    // concurrently at init time, and the worst that can happen is to leak
-    // a single instance. (c.f. VmLock)
-    static DmaMap* get();
-    static DmaMap* set(DmaMap* dmaMap);
-protected:
-
-    virtual void createMappingLocked(DmaBufferInfo* info);
-    virtual void removeMappingLocked(DmaBufferInfo* info);
-
-    // These are meant to be replaced by a real implementation
-    // in subclasses.
-    virtual void* doMap(uint64_t addr, uint64_t bufferSize) = 0;
-    virtual void doUnmap(void* mapped, uint64_t bufferSize) = 0;
-
-    std::unordered_map<uint64_t, DmaBufferInfo> mDmaBuffers;
-    android::base::ReadWriteLock mLock;
-    DISALLOW_COPY_ASSIGN_AND_MOVE(DmaMap);
-};
-
-} // namespace android
diff --git a/android/emulation/DmaMap_unittest.cpp b/android/emulation/DmaMap_unittest.cpp
deleted file mode 100644
index d5e23b8..0000000
--- a/android/emulation/DmaMap_unittest.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-// 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 "android/emulation/DmaMap.h"
-#include "android/emulation/testing/TestDmaMap.h"
-
-#include <gtest/gtest.h>
-
-using android::base::Optional;
-using android::base::kNullopt;
-
-namespace android {
-
-
-TEST(DmaMap, Default) {
-    // No default impl of DmaMap should exist on startup.
-    DmaMap* dmaMap = DmaMap::get();
-    ASSERT_FALSE(dmaMap);
-}
-
-TEST(DmaMap, CustomDmaMap) {
-    TestDmaMap myMap;
-    const DmaMapState& currState = myMap.dumpState();
-    EXPECT_EQ(currState.size(), 0);
-}
-
-TEST(DmaMap, SingleMapAdd) {
-    TestDmaMap myMap;
-    myMap.addBuffer(nullptr, 1, 2);
-    const DmaMapState& currState = myMap.dumpState();
-    const auto& it = currState.find(1);
-    EXPECT_TRUE(it != currState.end());
-    const DmaBufferInfo& info = it->second;
-    EXPECT_EQ(info.guestAddr, 1);
-    EXPECT_EQ(info.bufferSize, 2);
-    EXPECT_TRUE(info.currHostAddr);
-}
-
-TEST(DmaMap, SingleMapAddRemove) {
-    TestDmaMap myMap;
-    const DmaMapState& currState = myMap.dumpState();
-    myMap.addBuffer(nullptr, 1, 2);
-    const auto& it = currState.find(1);
-    EXPECT_TRUE(it != currState.end());
-    myMap.removeBuffer(1);
-    const auto& it2 = currState.find(1);
-    EXPECT_TRUE(it2 == currState.end());
-}
-
-TEST(DmaMap, SingleMapAddMulti) {
-    TestDmaMap myMap;
-    myMap.addBuffer(nullptr, 1, 2);
-    myMap.addBuffer(nullptr, 1, 3);
-    const DmaMapState& currState = myMap.dumpState();
-    const DmaBufferInfo& info = currState.find(1)->second;
-    EXPECT_EQ(info.guestAddr, 1);
-    EXPECT_EQ(info.bufferSize, 3);
-}
-
-TEST(DmaMap, MultiMap) {
-    TestDmaMap myMap;
-    myMap.addBuffer(nullptr, 1, 2);
-    myMap.addBuffer(nullptr, 3, 4);
-    const DmaMapState& currState = myMap.dumpState();
-    const auto& it1 = currState.find(1);
-    const auto& it3 = currState.find(3);
-    EXPECT_TRUE(it1 != currState.end());
-    EXPECT_TRUE(it3 != currState.end());
-    const DmaBufferInfo& info1 = it1->second;
-    const DmaBufferInfo& info3 = it3->second;
-    EXPECT_EQ(info1.guestAddr, 1);
-    EXPECT_EQ(info1.bufferSize, 2);
-    EXPECT_TRUE(info1.currHostAddr);
-    EXPECT_EQ(info3.guestAddr, 3);
-    EXPECT_EQ(info3.bufferSize, 4);
-    EXPECT_TRUE(info3.currHostAddr);
-    myMap.removeBuffer(1);
-    myMap.removeBuffer(3);
-    const auto& it1_notfound = currState.find(1);
-    const auto& it3_notfound = currState.find(3);
-    EXPECT_TRUE(it1_notfound == currState.end());
-    EXPECT_TRUE(it3_notfound == currState.end());
-}
-
-TEST(DmaMap, SingleMapHostRead) {
-    TestDmaMap myMap;
-    myMap.addBuffer(nullptr, 1, 2);
-    myMap.getHostAddr(1);
-
-    const DmaMapState& currState = myMap.dumpState();
-    const auto& it = currState.find(1);
-    const DmaBufferInfo& info = it->second;
-    EXPECT_EQ(info.guestAddr, 1);
-    EXPECT_EQ(info.bufferSize, 2);
-    EXPECT_TRUE(info.currHostAddr);
-
-    myMap.getHostAddr(1);
-    EXPECT_TRUE(currState.find(1)->second.currHostAddr);
-    myMap.getHostAddr(1);
-    EXPECT_TRUE(currState.find(1)->second.currHostAddr);
-}
-
-TEST(DmaMap, SingleMapHostReadInvalidate) {
-    TestDmaMap myMap;
-    myMap.addBuffer(nullptr, 1, 2);
-    myMap.getHostAddr(1);
-    myMap.invalidateHostMappings();
-    const DmaMapState& currState = myMap.dumpState();
-    const auto& it = currState.find(1);
-    const DmaBufferInfo& info = it->second;
-    EXPECT_EQ(info.guestAddr, 1);
-    EXPECT_EQ(info.bufferSize, 2);
-    EXPECT_FALSE(info.currHostAddr);
-}
-
-TEST(DmaMap, MultiMapHostReadInvalidate) {
-    TestDmaMap myMap;
-    const DmaMapState& currState = myMap.dumpState();
-    myMap.addBuffer(nullptr, 1, 2);
-    myMap.addBuffer(nullptr, 3, 4);
-    myMap.addBuffer(nullptr, 5, 6);
-    myMap.getHostAddr(1);
-    myMap.getHostAddr(3);
-    EXPECT_TRUE(currState.find(1)->second.currHostAddr);
-    EXPECT_TRUE(currState.find(3)->second.currHostAddr);
-    EXPECT_TRUE(currState.find(5)->second.currHostAddr);
-    myMap.invalidateHostMappings();
-    EXPECT_FALSE(currState.find(1)->second.currHostAddr);
-    EXPECT_FALSE(currState.find(3)->second.currHostAddr);
-    EXPECT_FALSE(currState.find(5)->second.currHostAddr);
-}
-
-TEST(DmaMap, MultiMapHostReadInvalidateRemap) {
-    TestDmaMap myMap;
-    const DmaMapState& currState = myMap.dumpState();
-    myMap.addBuffer(nullptr, 1, 2);
-    myMap.addBuffer(nullptr, 3, 4);
-    myMap.addBuffer(nullptr, 5, 6);
-    myMap.getHostAddr(1);
-    myMap.getHostAddr(3);
-    EXPECT_TRUE(currState.find(1)->second.currHostAddr);
-    EXPECT_TRUE(currState.find(3)->second.currHostAddr);
-    EXPECT_TRUE(currState.find(5)->second.currHostAddr);
-    myMap.invalidateHostMappings();
-    myMap.getHostAddr(3);
-    myMap.getHostAddr(5);
-    EXPECT_FALSE(currState.find(1)->second.currHostAddr);
-    EXPECT_TRUE(currState.find(3)->second.currHostAddr);
-    EXPECT_TRUE(currState.find(5)->second.currHostAddr);
-}
-
-TEST(DmaMap, ErrorCaseMapNonExistent) {
-    TestDmaMap myMap;
-    myMap.getHostAddr(1);
-}
-
-TEST(DmaMap, ErrorCaseRemoveNonExistent) {
-    TestDmaMap myMap;
-    myMap.removeBuffer(1);
-}
-
-} // namespace android
diff --git a/android/emulation/GoldfishDma.cpp b/android/emulation/GoldfishDma.cpp
deleted file mode 100644
index 1e5bf9f..0000000
--- a/android/emulation/GoldfishDma.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "android/base/memory/LazyInstance.h"
-
-#include "android/emulation/GoldfishDma.h"
-#include "android/emulation/DmaMap.h"
-
-#include "android/emulation/android_pipe_host.h"
-#include "android/utils/assert.h"
-#include "android/utils/debug.h"
-#include "android/utils/system.h"
-
-static void android_goldfish_dma_add_buffer(void* pipe, uint64_t guest_paddr, uint64_t sz) {
-    android::DmaMap::get()->addBuffer(pipe, guest_paddr, sz);
-}
-
-static void android_goldfish_dma_remove_buffer(uint64_t guest_paddr) {
-    android::DmaMap::get()->removeBuffer(guest_paddr);
-}
-
-static void* android_goldfish_dma_get_host_addr(uint64_t guest_paddr) {
-    return android::DmaMap::get()->getHostAddr(guest_paddr);
-}
-
-static void android_goldfish_dma_invalidate_host_mappings() {
-    android::DmaMap::get()->invalidateHostMappings();
-}
-
-static void android_goldfish_dma_unlock(uint64_t guest_paddr) {
-    void* hwpipe = android::DmaMap::get()->getPipeInstance(guest_paddr);
-    android_pipe_host_signal_wake(hwpipe, PIPE_WAKE_UNLOCK_DMA);
-}
-
-static void android_goldfish_dma_reset_host_mappings() {
-    android::DmaMap::get()->resetHostMappings();
-}
-
-GoldfishDmaOps android_goldfish_dma_ops = {
-    .add_buffer = android_goldfish_dma_add_buffer,
-    .remove_buffer = android_goldfish_dma_remove_buffer,
-    .get_host_addr = android_goldfish_dma_get_host_addr,
-    .invalidate_host_mappings = android_goldfish_dma_invalidate_host_mappings,
-    .unlock = android_goldfish_dma_unlock,
-    .reset_host_mappings = android_goldfish_dma_reset_host_mappings,
-};
diff --git a/android/emulation/GoldfishDma.h b/android/emulation/GoldfishDma.h
deleted file mode 100644
index d28e5b7..0000000
--- a/android/emulation/GoldfishDma.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (C) 2016 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-*/
-
-#pragma once
-
-#include <inttypes.h>
-
-static const uint32_t kDmaBufSizeMB = 32;
-// GOLDFISH DMA
-//
-// Goldfish DMA is an extension to the pipe device
-// and is designed to facilitate high-speed RAM->RAM
-// transfers from guest to host.
-//
-// See docs/GOLDFISH-VIRTUAL-HARDWARE.txt and
-//     docs/ANDROID-QEMU-PIPE.txt
-//
-// for more details.
-// Host / virtual device interface:
-typedef struct {
-// add_buffer():
-// Tell us that there is a physically-contiguous buffer in the guest
-// starting at |guest_paddr|. This should be used upon allocation
-// of the DMA buffer in the ugest.
-void (*add_buffer)(void* pipe, uint64_t guest_paddr, uint64_t sz);
-// remove_buffer():
-// Tell us that we don't care about tracking this buffer anymore.
-// This should usually be used when the DMA buffer has been freed
-// in the ugest.
-void (*remove_buffer)(uint64_t guest_paddr);
-// get_host_addr():
-// Obtain a pointer to guest physical memory that is usable as
-// as host void*.
-void* (*get_host_addr)(uint64_t guest_paddr);
-// invalidate_host_mappings():
-// Sometimes (say, on snapshot save/load) we may need to re-map
-// the guest DMA buffers so to regain access to them.
-// This function tells our map of DMA buffers to remap the buffers
-// next time they are used.
-void (*invalidate_host_mappings)(void);
-// unlock():
-// Unlocks the buffer at |guest_paddr| to signal the guest
-// that we are done writing it.
-void (*unlock)(uint64_t guest_paddr);
-// reset_host_mappings();
-// Not only invalidates the mappings, but also removes them from the record.
-void (*reset_host_mappings)(void);
-} GoldfishDmaOps;
-
-extern GoldfishDmaOps android_goldfish_dma_ops;
diff --git a/android/emulation/testing/TestDmaMap.h b/android/emulation/testing/TestDmaMap.h
deleted file mode 100644
index c71fe9d..0000000
--- a/android/emulation/testing/TestDmaMap.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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 "android/emulation/DmaMap.h"
-
-#include <unordered_map>
-#include <vector>
-
-namespace android {
-
-typedef std::unordered_map<uint64_t, DmaBufferInfo> DmaMapState;
-
-class TestDmaMap : public DmaMap {
-public:
-    TestDmaMap() : mOldDmaMap(DmaMap::set(this)), mInstalled(true) {}
-
-    ~TestDmaMap() { release(); }
-
-    void release() {
-        if (mInstalled) {
-            // NOTE: A value of nullptr for mOldDmaMap is valid.
-            DmaMap::set(mOldDmaMap);
-            mInstalled = false;
-        }
-    }
-
-    const DmaMapState& dumpState() {
-        return mDmaBuffers;
-    }
-
-    virtual void* doMap(uint64_t addr, uint64_t buffer) { return nullptr; }
-    virtual void doUnmap(void* mapped, uint64_t buffer) { }
-
-    DmaMap* mOldDmaMap = nullptr;
-    bool mInstalled = false;
-};
-
-} // namespace android
diff --git a/host/commands/gen-entries.py b/host/commands/gen-entries.py
index a122ef7..fbfdb4d 100755
--- a/host/commands/gen-entries.py
+++ b/host/commands/gen-entries.py
@@ -61,7 +61,7 @@
 
     # Remove path from first parameter
     argv = argv[:]
-    argv[0] = "android/scripts/gen-entries.py"
+    argv[0] = "host/commands/gen-entries.py"
     return ' '.join(argv)
 
 def parse_entries_file(lines):
@@ -151,165 +151,6 @@
     print ""
     print "#endif  // %s_FUNCTIONS_H" % prefix_name
 
-
-
-# The purpose of gen_translator()
-# is to quickly generate implementations on the host Translator,
-# which processes commands that just got onto the renderthread off goldfish pipe
-# and are fed to system OpenGL.
-
-def gen_translator(entries):
-    # Definitions for custom implementation bodies go in
-    # android/scripts/gles3translatorgen/gles30_custom.py
-    # android/scripts/gles3translatorgen/gles31_custom.py
-    from gles3translatorgen import gles30_custom
-    from gles3translatorgen import gles31_custom
-
-    translator_custom_share_processing = { }
-    for (k, v) in gles30_custom.custom_share_processing.items():
-        translator_custom_share_processing[k] = v
-    for (k, v) in gles31_custom.custom_share_processing.items():
-        translator_custom_share_processing[k] = v
-
-    translator_custom_pre = { }
-    for (k, v) in gles30_custom.custom_preprocesses.items():
-        translator_custom_pre[k] = v
-    for (k, v) in gles31_custom.custom_preprocesses.items():
-        translator_custom_pre[k] = v
-
-    translator_custom_post = { }
-    for (k, v) in gles30_custom.custom_postprocesses.items():
-        translator_custom_post[k] = v
-    for (k, v) in gles31_custom.custom_postprocesses.items():
-        translator_custom_post[k] = v
-
-    translator_no_passthrough = {}
-    for (k, v) in gles30_custom.no_passthrough.items():
-        translator_no_passthrough[k] = v
-    for (k, v) in gles31_custom.no_passthrough.items():
-        translator_no_passthrough[k] = v
-
-    translator_needexternc = {
-            "glGetStringi": 1,
-            "glUniform4ui": 1,
-            "glGetUniformIndices": 1,
-            "glTransformFeedbackVaryings": 1,
-            "glCreateShaderProgramv": 1,
-            "glProgramUniform2ui": 1,
-            "glProgramUniform3ui": 1,
-            "glProgramUniform4ui": 1,
-            "glBindVertexBuffer": 1,
-    };
-    translator_nocontext_fail_codes = {
-            "glClientWaitSync" : "GL_WAIT_FAILED",
-    };
-    def needExternC(entry):
-        if translator_needexternc.has_key(entry.func_name):
-            return "extern \"C\" "
-        else:
-            return ""
-    def get_fail_code(entry):
-        if translator_nocontext_fail_codes.has_key(entry.func_name):
-            return translator_nocontext_fail_codes[entry.func_name];
-        else:
-            return "0"
-    def gen_cxt_getter(entry):
-        if (entry.return_type == "void"):
-            print "    GET_CTX_V2();"
-        else:
-            print "    GET_CTX_V2_RET(%s);" % get_fail_code(entry)
-
-    def gen_validations_custom_impl(entry):
-        isGen = entry.func_name.startswith("glGen")
-        isDelete = entry.func_name.startswith("glDelete")
-        isBufferOp = "Buffer" in entry.func_name
-
-        hasTargetArg = "target" in entry.varnames
-        hasProgramArg = "program" in entry.varnames
-
-        def mySetError(condition, glerr):
-            if entry.return_type == "void":
-                return "SET_ERROR_IF(%s,%s)" % (condition, glerr);
-            else:
-                return "RET_AND_SET_ERROR_IF(%s,%s,%s)" % (condition, glerr, get_fail_code(entry));
-
-        if (isGen or isDelete) and ("n" in entry.varnames):
-            print "    %s;" % mySetError("n < 0", "GL_INVALID_VALUE");
-        if (isBufferOp and hasTargetArg):
-            print "    %s;" % mySetError("!GLESv2Validate::bufferTarget(ctx, target)", "GL_INVALID_ENUM");
-        if translator_custom_pre.has_key(entry.func_name):
-            print translator_custom_pre[entry.func_name],
-
-    def gen_call_ret(entry):
-        globalNameTypes = {
-                ("GLuint", "program") : "NamedObjectType::SHADER_OR_PROGRAM",
-                ("GLuint", "texture") : "NamedObjectType::TEXTURE",
-                ("GLuint", "buffer") : "NamedObjectType::VERTEXBUFFER",
-                ("GLuint", "sampler") : "NamedObjectType::SAMPLER",
-                ("GLuint", "query") : "NamedObjectType::QUERY",
-        }
-        globalNames = {
-                ("GLuint", "program") : "globalProgramName",
-                ("GLuint", "texture") : "globalTextureName",
-                ("GLuint", "buffer") : "globalBufferName",
-                ("GLuint", "sampler") : "globalSampler",
-                ("GLuint", "query") : "globalQuery",
-        }
-
-        needsShareGroup = False
-        for v in zip(entry.vartypes, entry.varnames):
-            if v in globalNameTypes.keys():
-                needsShareGroup = True
-
-        if needsShareGroup:
-            print "    if (ctx->shareGroup().get()) {"
-            for key in zip(entry.vartypes, entry.varnames):
-                vartype, varname = key
-                if globalNames.has_key(key):
-                    print "        const GLuint %s = ctx->shareGroup()->getGlobalName(%s, %s);" % (globalNames[key], globalNameTypes[key], varname)
-
-        globalCall = ", ".join(map(lambda k: globalNames.get(k, k[1]), zip(entry.vartypes, entry.varnames)))
-
-        if needsShareGroup and translator_custom_share_processing.has_key(entry.func_name):
-            print translator_custom_share_processing[entry.func_name],
-
-        if (entry.return_type == "void"):
-            if (needsShareGroup):
-                print "   ",
-
-            if not translator_no_passthrough.has_key(entry.func_name):
-                print "    ctx->dispatcher().%s(%s);" % (entry.func_name, globalCall)
-
-            if needsShareGroup:
-                print "    }"
-            if translator_custom_post.has_key(entry.func_name):
-                print translator_custom_post[entry.func_name];
-        else:
-            if (needsShareGroup):
-                print "   ",
-            if not translator_no_passthrough.has_key(entry.func_name):
-                print "    %s %s = ctx->dispatcher().%s(%s);" % (entry.return_type, entry.func_name + "RET", entry.func_name, globalCall)
-            else:
-                print "    %s %s = %s" % (entry.return_type, entry_func_name + "RET", get_fail_code(entry))
-
-            if translator_custom_post.has_key(entry.func_name):
-                print translator_custom_post[entry.func_name];
-
-            print "    return %s;" % (entry.func_name + "RET");
-            if needsShareGroup:
-                print "    } else return %s;" % (get_fail_code(entry))
-
-    print "// Auto-generated with: %s" % banner_command(sys.argv)
-    print "// This file is best left unedited."
-    print "// Try to make changes through gen_translator in gen-entries.py,"
-    print "// and/or parcel out custom functionality in separate code."
-    for entry in entries:
-        print "%sGL_APICALL %s GL_APIENTRY %s(%s) {" % (needExternC(entry), entry.return_type, entry.func_name, entry.parameters)
-        gen_cxt_getter(entry);
-        gen_validations_custom_impl(entry);
-        gen_call_ret(entry);
-        print "}\n"
-
 def gen_dll_wrapper(entries, prefix_name, verbatim, filename):
     """Generate a C source file that contains functions that act as wrappers
        for entry points located in another shared library. This allows the
@@ -423,8 +264,6 @@
         gen_windows_def_file(entries)
     elif mode == 'sym':
         gen_unix_sym_file(entries)
-    elif mode == 'translator_passthrough':
-        gen_translator(entries)
     elif mode == 'wrapper':
         gen_dll_wrapper(entries, prefix_name, verbatim, filename)
     elif mode == 'symbols':
@@ -439,7 +278,7 @@
 
 # List of valid --mode option values.
 mode_list = [
-    'def', 'sym', 'translator_passthrough', 'wrapper', 'symbols', '_symbols', 'functions', 'funcargs'
+    'def', 'sym', 'wrapper', 'symbols', '_symbols', 'functions', 'funcargs'
 ]
 
 # Argument parsing.
diff --git a/host/libs/Android.bp b/host/libs/Android.bp
new file mode 100644
index 0000000..99a3ff0
--- /dev/null
+++ b/host/libs/Android.bp
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2017 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.
+
+subdirs = [
+    "adb_connection_maintainer",
+    "config",
+    "ivserver",
+    "monitor",
+    "usbip",
+    "virglrenderer",
+    "vm_manager",
+]
diff --git a/host/libs/virglrenderer/.clang-format b/host/libs/virglrenderer/.clang-format
new file mode 100644
index 0000000..4b84118
--- /dev/null
+++ b/host/libs/virglrenderer/.clang-format
@@ -0,0 +1,17 @@
+BasedOnStyle: Google
+AccessModifierOffset: -2
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/host/libs/virglrenderer/.gitignore b/host/libs/virglrenderer/.gitignore
new file mode 100644
index 0000000..562939a
--- /dev/null
+++ b/host/libs/virglrenderer/.gitignore
@@ -0,0 +1,3 @@
+renderControl_dec/renderControl_server_context.cpp
+GLESv1_dec/gles1_server_context.cpp
+GLESv3_dec/gles3_server_context.cpp
diff --git a/host/libs/virglrenderer/AVDVirglRenderer.cpp b/host/libs/virglrenderer/AVDVirglRenderer.cpp
new file mode 100644
index 0000000..a089489
--- /dev/null
+++ b/host/libs/virglrenderer/AVDVirglRenderer.cpp
@@ -0,0 +1,1092 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+#undef NDEBUG
+
+extern "C" {
+#include <linux/virtio_gpu.h>
+#include <virgl/virglrenderer.h>
+#include <virgl_hw.h>
+}
+
+#include <sys/uio.h>
+
+#include <dlfcn.h>
+#include <algorithm>
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <deque>
+#include <map>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES3/gl31.h>
+#include <GLES3/gl3ext.h>
+
+#include <drm/drm_fourcc.h>
+
+#include <OpenGLESDispatch/EGLDispatch.h>
+#include <OpenGLESDispatch/GLESv1Dispatch.h>
+#include <OpenGLESDispatch/GLESv3Dispatch.h>
+
+#include "OpenglRender/IOStream.h"
+
+#include "Context.h"
+#include "EglConfig.h"
+#include "EglContext.h"
+#include "EglSurface.h"
+#include "EglSync.h"
+#include "Resource.h"
+
+#include <VirtioGpuCmd.h>
+
+// for debug only
+#include <sys/syscall.h>
+#include <unistd.h>
+#define gettid() (int)syscall(__NR_gettid)
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 0x1000
+#endif
+
+#define MAX_CMDRESPBUF_SIZE (10 * PAGE_SIZE)
+
+#define ALIGN(A, B) (((A) + (B)-1) / (B) * (B))
+
+// Enable passing scanout buffers as texture names to sdl2 backend
+#define QEMU_HARDWARE_GL_INTEROP
+
+#ifdef QEMU_HARDWARE_GL_INTEROP
+typedef GLenum (*PFNGLGETERROR)(void);
+typedef void (*PFNGLBINDTEXTURE)(GLenum target, GLuint texture);
+typedef void (*PFNGLGENTEXTURES)(GLsizei n, GLuint* textures);
+typedef void (*PFNGLTEXPARAMETERI)(GLenum target, GLenum pname, GLint param);
+typedef void (*PFNGLPIXELSTOREI)(GLenum pname, GLint param);
+typedef void (*PFNGLTEXIMAGE2D)(GLenum target, GLint level, GLint internalformat, GLsizei width,
+                                GLsizei height, GLint border, GLenum format, GLenum type,
+                                const void* pixels);
+static PFNGLBINDTEXTURE g_glBindTexture;
+static PFNGLGENTEXTURES g_glGenTextures;
+static PFNGLTEXPARAMETERI g_glTexParameteri;
+static PFNGLPIXELSTOREI g_glPixelStorei;
+static PFNGLTEXIMAGE2D g_glTexImage2D;
+static virgl_renderer_gl_context g_ctx0_alt;
+#endif
+
+// Global state
+std::map<uint32_t, EglContext*> EglContext::map;
+std::map<uint32_t, EglSurface*> EglSurface::map;
+std::map<uint32_t, EglImage*> EglImage::map;
+std::map<uint32_t, Resource*> Resource::map;
+std::map<uint64_t, EglSync*> EglSync::map;
+std::map<uint32_t, Context*> Context::map;
+std::vector<EglConfig*> EglConfig::vec;
+static virgl_renderer_callbacks* g_cb;
+const EGLint EglConfig::kAttribs[];
+uint32_t EglContext::nextId = 1U;
+uint32_t EglSurface::nextId = 1U;
+uint32_t EglImage::nextId = 1U;
+uint64_t EglSync::nextId = 1U;
+static void* g_cookie;
+
+// Fence queue, must be thread safe
+static std::mutex g_fence_deque_mutex;
+static std::deque<int> g_fence_deque;
+
+// Other GPU context and state
+static EGLSurface g_ctx0_surface;
+static EGLContext g_ctx0_es1;
+static EGLContext g_ctx0_es2;
+static EGLDisplay g_dpy;
+
+// Last context receiving a command. Allows us to find the context a fence is
+// being created for. Works around the poorly designed virgl interface.
+static Context* g_last_submit_cmd_ctx;
+
+#ifdef OPENGL_DEBUG_PRINTOUT
+
+#include "emugl/common/logging.h"
+
+// For logging from the protocol decoders
+
+void default_logger(const char* fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    va_end(ap);
+}
+
+emugl_logger_t emugl_cxt_logger = default_logger;
+
+#endif
+
+static void dump_global_state(void) {
+    printf("AVDVIRGLRENDERER GLOBAL STATE\n\n");
+
+    printf("Resources:\n");
+    for (auto const& it : Resource::map) {
+        Resource const* res = it.second;
+
+        printf(
+            "  Resource %u: %ux%u 0x%x %p (%zub) t=%u b=%u d=%u a=%u l=%u "
+            "n=%u f=%u\n",
+            res->args.handle, res->args.width, res->args.height, res->args.format,
+            res->iov ? res->iov[0].iov_base : nullptr, res->iov ? res->iov[0].iov_len : 0,
+            res->args.target, res->args.bind, res->args.depth, res->args.array_size,
+            res->args.last_level, res->args.nr_samples, res->args.flags);
+
+        for (auto const& it : res->context_map) {
+            Context const* ctx = it.second;
+
+            printf("    Context %u, pid=%d, tid=%d\n", ctx->handle, ctx->pid, ctx->tid);
+        }
+    }
+
+    printf("Contexts:\n");
+    for (auto const& it : Context::map) {
+        Context const* ctx = it.second;
+
+        printf("  Context %u: %s pid=%u tid=%u\n", ctx->handle, ctx->name.c_str(), ctx->pid,
+               ctx->tid);
+
+        for (auto const& it : ctx->resource_map) {
+            Resource const* res = it.second;
+
+            printf("    Resource %u\n", res->args.handle);
+        }
+    }
+}
+
+static int sync_linear_to_iovec(Resource* res, uint64_t offset, const virgl_box* box) {
+    uint32_t bpp;
+    switch (res->args.format) {
+        case VIRGL_FORMAT_R8_UNORM:
+            bpp = 1U;
+            break;
+        case VIRGL_FORMAT_B5G6R5_UNORM:
+            bpp = 2U;
+            break;
+        default:
+            bpp = 4U;
+            break;
+    }
+
+    if (box->x > res->args.width || box->y > res->args.height)
+        return 0;
+    if (box->w == 0U || box->h == 0U)
+        return 0;
+    uint32_t w = std::min(box->w, res->args.width - box->x);
+    uint32_t h = std::min(box->h, res->args.height - box->y);
+    uint32_t stride = ALIGN(res->args.width * bpp, 16U);
+    offset += box->y * stride + box->x * bpp;
+    size_t length = (h - 1U) * stride + w * bpp;
+    if (offset + length > res->linearSize)
+        return EINVAL;
+
+    if (res->num_iovs > 1) {
+        const char* linear = static_cast<const char*>(res->linear);
+        for (uint32_t i = 0, iovOffset = 0U; length && i < res->num_iovs; i++) {
+            if (iovOffset + res->iov[i].iov_len > offset) {
+                char* iov_base = static_cast<char*>(res->iov[i].iov_base);
+                size_t copyLength = std::min(length, res->iov[i].iov_len);
+                memcpy(iov_base + offset - iovOffset, linear, copyLength);
+                linear += copyLength;
+                offset += copyLength;
+                length -= copyLength;
+            }
+            iovOffset += res->iov[i].iov_len;
+        }
+    }
+
+    return 0;
+}
+
+static int sync_iovec_to_linear(Resource* res, uint64_t offset, const virgl_box* box) {
+    uint32_t bpp;
+    switch (res->args.format) {
+        case VIRGL_FORMAT_R8_UNORM:
+            bpp = 1U;
+            break;
+        case VIRGL_FORMAT_B5G6R5_UNORM:
+            bpp = 2U;
+            break;
+        default:
+            bpp = 4U;
+            break;
+    }
+
+    if (box->x > res->args.width || box->y > res->args.height)
+        return 0;
+    if (box->w == 0U || box->h == 0U)
+        return 0;
+    uint32_t w = std::min(box->w, res->args.width - box->x);
+    uint32_t h = std::min(box->h, res->args.height - box->y);
+    uint32_t stride = ALIGN(res->args.width * bpp, 16U);
+    offset += box->y * stride + box->x * bpp;
+    size_t length = (h - 1U) * stride + w * bpp;
+    if (offset + length > res->linearSize)
+        return EINVAL;
+
+    if (res->num_iovs > 1) {
+        char* linear = static_cast<char*>(res->linear);
+        for (uint32_t i = 0, iovOffset = 0U; length && i < res->num_iovs; i++) {
+            if (iovOffset + res->iov[i].iov_len > offset) {
+                const char* iov_base = static_cast<const char*>(res->iov[i].iov_base);
+                size_t copyLength = std::min(length, res->iov[i].iov_len);
+                memcpy(linear, iov_base + offset - iovOffset, copyLength);
+                linear += copyLength;
+                offset += copyLength;
+                length -= copyLength;
+            }
+            iovOffset += res->iov[i].iov_len;
+        }
+    }
+
+    return 0;
+}
+
+// The below API was defined by virglrenderer 'master', but does not seem to
+// be used by QEMU, so just ignore it for now..
+//
+// virgl_renderer_get_rect
+// virgl_renderer_get_fd_for_texture
+// virgl_renderer_cleanup
+// virgl_renderer_reset
+// virgl_renderer_get_poll_fd
+
+int virgl_renderer_init(void* cookie, int flags, virgl_renderer_callbacks* cb) {
+    if (!cookie || !cb)
+        return EINVAL;
+
+    if (flags != 0)
+        return ENOSYS;
+
+    if (cb->version != 1)
+        return ENOSYS;
+
+#ifdef QEMU_HARDWARE_GL_INTEROP
+    // FIXME: If we just use "libGL.so" here, mesa's interception library returns
+    //        stub dlsyms that do nothing at runtime, even after binding..
+    void* handle = dlopen(
+        "/usr/lib/x86_64-linux-gnu/nvidia/"
+        "current/libGL.so.384.111",
+        RTLD_NOW);
+    assert(handle != nullptr);
+    g_glBindTexture = (PFNGLBINDTEXTURE)dlsym(handle, "glBindTexture");
+    assert(g_glBindTexture != nullptr);
+    g_glGenTextures = (PFNGLGENTEXTURES)dlsym(handle, "glGenTextures");
+    assert(g_glGenTextures != nullptr);
+    g_glTexParameteri = (PFNGLTEXPARAMETERI)dlsym(handle, "glTexParameteri");
+    assert(g_glTexParameteri != nullptr);
+    g_glPixelStorei = (PFNGLPIXELSTOREI)dlsym(handle, "glPixelStorei");
+    assert(g_glPixelStorei != nullptr);
+    g_glTexImage2D = (PFNGLTEXIMAGE2D)dlsym(handle, "glTexImage2D");
+    assert(g_glTexImage2D != nullptr);
+#endif
+
+    if (!egl_dispatch_init())
+        return ENOENT;
+
+    if (!gles1_dispatch_init())
+        return ENOENT;
+
+    if (!gles3_dispatch_init())
+        return ENOENT;
+
+    g_dpy = s_egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    if (g_dpy == EGL_NO_DISPLAY) {
+        printf("Failed to open default EGL display\n");
+        return ENOENT;
+    }
+
+    if (!s_egl.eglInitialize(g_dpy, nullptr, nullptr)) {
+        printf("Failed to initialize EGL display\n");
+        g_dpy = EGL_NO_DISPLAY;
+        return ENOENT;
+    }
+
+    EGLint nConfigs;
+    if (!s_egl.eglGetConfigs(g_dpy, nullptr, 0, &nConfigs)) {
+        printf("Failed to retrieve number of EGL configs\n");
+        s_egl.eglTerminate(g_dpy);
+        g_dpy = EGL_NO_DISPLAY;
+        return ENOENT;
+    }
+
+    EGLConfig configs[nConfigs];
+    if (!s_egl.eglGetConfigs(g_dpy, configs, nConfigs, &nConfigs)) {
+        printf("Failed to retrieve EGL configs\n");
+        s_egl.eglTerminate(g_dpy);
+        g_dpy = EGL_NO_DISPLAY;
+        return ENOENT;
+    }
+    for (EGLint c = 0; c < nConfigs; c++) {
+        EGLint configId;
+        if (!s_egl.eglGetConfigAttrib(g_dpy, configs[c], EGL_CONFIG_ID, &configId)) {
+            printf("Failed to retrieve EGL config ID\n");
+            s_egl.eglTerminate(g_dpy);
+            g_dpy = EGL_NO_DISPLAY;
+            return ENOENT;
+        }
+        EglConfig* config =
+            new (std::nothrow) EglConfig(g_dpy, configs[c], s_egl.eglGetConfigAttrib);
+        if (!config)
+            return ENOMEM;
+    }
+
+    // clang-format off
+    EGLint const attrib_list[] = {
+        EGL_CONFORMANT,   EGL_OPENGL_ES_BIT | EGL_OPENGL_ES3_BIT_KHR,
+        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+        EGL_NONE,
+     };
+    // clang-format on
+    EGLint num_config = 0;
+    EGLConfig config;
+    if (!s_egl.eglChooseConfig(g_dpy, attrib_list, &config, 1, &num_config) || num_config != 1) {
+        printf("Failed to select ES1 & ES3 capable EGL config\n");
+        s_egl.eglTerminate(g_dpy);
+        g_dpy = EGL_NO_DISPLAY;
+        return ENOENT;
+    }
+
+    // clang-format off
+    EGLint const pbuffer_attrib_list[] = {
+        EGL_WIDTH,  1,
+        EGL_HEIGHT, 1,
+        EGL_NONE
+    };
+    // clang-format on
+    g_ctx0_surface = s_egl.eglCreatePbufferSurface(g_dpy, config, pbuffer_attrib_list);
+    if (!g_ctx0_surface) {
+        printf("Failed to create pbuffer surface for context 0\n");
+        s_egl.eglTerminate(g_dpy);
+        g_dpy = EGL_NO_DISPLAY;
+        return ENOENT;
+    }
+
+    // clang-format off
+    EGLint const es1_attrib_list[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 1,
+        EGL_NONE
+    };
+    // clang-format on
+    g_ctx0_es1 = s_egl.eglCreateContext(g_dpy, config, EGL_NO_CONTEXT, es1_attrib_list);
+    if (g_ctx0_es1 == EGL_NO_CONTEXT) {
+        printf("Failed to create ES1 context 0\n");
+        s_egl.eglDestroySurface(g_dpy, g_ctx0_surface);
+        s_egl.eglTerminate(g_dpy);
+        g_dpy = EGL_NO_DISPLAY;
+        return ENOENT;
+    }
+
+    // clang-format off
+    EGLint const es2_attrib_list[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 3, // yes, 3
+        EGL_NONE
+    };
+    // clang-format on
+    g_ctx0_es2 = s_egl.eglCreateContext(g_dpy, config, EGL_NO_CONTEXT, es2_attrib_list);
+    if (g_ctx0_es2 == EGL_NO_CONTEXT) {
+        printf("Failed to create ES2 context 0\n");
+        s_egl.eglDestroySurface(g_dpy, g_ctx0_surface);
+        s_egl.eglDestroyContext(g_dpy, g_ctx0_es1);
+        g_ctx0_es1 = EGL_NO_CONTEXT;
+        s_egl.eglTerminate(g_dpy);
+        g_dpy = EGL_NO_DISPLAY;
+    }
+
+#ifdef QEMU_HARDWARE_GL_INTEROP
+    // This is the hardware GPU context. In future, this code should probably
+    // be removed and SwiftShader be used for all presentation blits.
+    virgl_renderer_gl_ctx_param ctx_params = {
+        .major_ver = 3,
+        .minor_ver = 0,
+    };
+    g_ctx0_alt = cb->create_gl_context(cookie, 0, &ctx_params);
+    if (!g_ctx0_alt) {
+        printf("Failed to create hardware GL context 0\n");
+        s_egl.eglDestroySurface(g_dpy, g_ctx0_surface);
+        s_egl.eglDestroyContext(g_dpy, g_ctx0_es1);
+        g_ctx0_es1 = EGL_NO_CONTEXT;
+        s_egl.eglTerminate(g_dpy);
+        g_dpy = EGL_NO_DISPLAY;
+    }
+
+    // Test we can actually make it current; otherwise, bail
+    if (cb->make_current(cookie, 0, g_ctx0_alt)) {
+        printf("Failed to make hardware GL context 0 current\n");
+        cb->destroy_gl_context(cookie, g_ctx0_alt);
+        g_ctx0_alt = nullptr;
+        s_egl.eglDestroySurface(g_dpy, g_ctx0_surface);
+        s_egl.eglDestroyContext(g_dpy, g_ctx0_es1);
+        g_ctx0_es1 = EGL_NO_CONTEXT;
+        s_egl.eglTerminate(g_dpy);
+        g_dpy = EGL_NO_DISPLAY;
+    }
+#endif
+
+    EglContext::nextId = 1U;
+    g_cookie = cookie;
+    g_cb = cb;
+    return 0;
+}
+
+void virgl_renderer_poll(void) {
+    std::lock_guard<std::mutex> lk(g_fence_deque_mutex);
+    for (auto fence : g_fence_deque)
+        g_cb->write_fence(g_cookie, fence);
+    g_fence_deque.clear();
+}
+
+void* virgl_renderer_get_cursor_data(uint32_t resource_id, uint32_t* width, uint32_t* height) {
+    if (!width || !height)
+        return nullptr;
+
+    std::map<uint32_t, Resource*>::iterator it;
+    it = Resource::map.find(resource_id);
+    if (it == Resource::map.end())
+        return nullptr;
+
+    Resource* res = it->second;
+    if (res->args.bind != VIRGL_RES_BIND_CURSOR)
+        return nullptr;
+
+    void* pixels = malloc(res->linearSize);
+    memcpy(pixels, res->linear, res->linearSize);
+    *height = res->args.height;
+    *width = res->args.width;
+    return pixels;
+}
+
+// NOTE: This function is called from thread context. Do not touch anything
+// without a mutex to protect it from concurrent access. Everything else in
+// libvirglrenderer is designed to be single-threaded *only*.
+
+// Hack to serialize all calls into EGL or GLES functions due to bugs in
+// swiftshader. This should be removed as soon as possible.
+static std::mutex swiftshader_wa_mutex;
+
+static void process_cmd(Context* ctx, char* buf, size_t bufSize, int fence) {
+    VirtioGpuCmd* cmd_resp = reinterpret_cast<VirtioGpuCmd*>(ctx->cmd_resp->linear);
+
+    IOStream stream(cmd_resp->buf, MAX_CMDRESPBUF_SIZE - sizeof(*cmd_resp));
+
+    {
+        std::lock_guard<std::mutex> lk(swiftshader_wa_mutex);
+        size_t decodedBytes;
+
+        decodedBytes = ctx->render_control.decode(buf, bufSize, &stream, &ctx->checksum_calc);
+        bufSize -= decodedBytes;
+        buf += decodedBytes;
+
+        decodedBytes = ctx->gles1.decode(buf, bufSize, &stream, &ctx->checksum_calc);
+        bufSize -= decodedBytes;
+        buf += decodedBytes;
+
+        decodedBytes = ctx->gles3.decode(buf, bufSize, &stream, &ctx->checksum_calc);
+        bufSize -= decodedBytes;
+        buf += decodedBytes;
+    }
+
+    assert(bufSize == 0);
+
+    cmd_resp->cmdSize += stream.getFlushSize();
+
+    printf("(tid %d) ctx %d: cmd %u, size %zu, fence %d\n", gettid(), ctx->handle, cmd_resp->op,
+           cmd_resp->cmdSize - sizeof(*cmd_resp), fence);
+    if (cmd_resp->cmdSize - sizeof(*cmd_resp) > 0) {
+        printf("(tid %d) ", gettid());
+        for (size_t i = 0; i < cmd_resp->cmdSize - sizeof(*cmd_resp); i++) {
+            printf("%.2x ", (unsigned char)cmd_resp->buf[i]);
+        }
+        printf("\n");
+    }
+
+    virgl_box box = {
+        .w = cmd_resp->cmdSize,
+        .h = 1,
+    };
+    sync_linear_to_iovec(ctx->cmd_resp, 0, &box);
+
+    {
+        std::lock_guard<std::mutex> lk(g_fence_deque_mutex);
+        g_fence_deque.push_back(fence);
+    }
+}
+
+int virgl_renderer_submit_cmd(void* buffer, int ctx_id, int ndw) {
+    VirtioGpuCmd* cmd = static_cast<VirtioGpuCmd*>(buffer);
+    size_t bufSize = sizeof(uint32_t) * ndw;
+
+    if (bufSize < sizeof(*cmd)) {
+        printf("bad buffer size, bufSize=%zu, ctx=%d\n", bufSize, ctx_id);
+        return -1;
+    }
+
+    printf("ctx %d: cmd %u, size %zu\n", ctx_id, cmd->op, cmd->cmdSize - sizeof(*cmd));
+
+    for (size_t i = 0; i < bufSize - sizeof(*cmd); i++) {
+        printf("%.2x ", (unsigned char)cmd->buf[i]);
+    }
+    printf("\n");
+
+    if (cmd->cmdSize < bufSize) {
+        printf("ignoring short command, cmdSize=%u, bufSize=%zu\n", cmd->cmdSize, bufSize);
+        return 0;
+    }
+
+    if (cmd->cmdSize > bufSize) {
+        printf("command would overflow buffer, cmdSize=%u, bufSize=%zu\n", cmd->cmdSize, bufSize);
+        return -1;
+    }
+
+    std::map<uint32_t, Context*>::iterator it;
+    it = Context::map.find((uint32_t)ctx_id);
+    if (it == Context::map.end()) {
+        printf("command submit from invalid context %d, ignoring\n", ctx_id);
+        return 0;
+    }
+
+    Context* ctx = it->second;
+
+    // When the context is created, the remote side should send a test command
+    // (op == 0) which we use to set up our link to this context's 'response
+    // buffer'. Only apps using EGL or GLES have this. Gralloc contexts will
+    // never hit this path because they do not submit 3D commands.
+    if (cmd->op == 0) {
+        std::map<uint32_t, Resource*>::iterator it;
+        it = Resource::map.find(*(uint32_t*)cmd->buf);
+        if (it != Resource::map.end()) {
+            Resource* res = it->second;
+            size_t cmdRespBufSize = 0U;
+            for (size_t i = 0; i < res->num_iovs; i++)
+                cmdRespBufSize += res->iov[i].iov_len;
+            if (cmdRespBufSize == MAX_CMDRESPBUF_SIZE)
+                ctx->cmd_resp = res;
+        }
+    }
+
+    if (!ctx->cmd_resp) {
+        printf("context command response page not set up, ctx=%d\n", ctx_id);
+        return -1;
+    }
+
+    VirtioGpuCmd* cmd_resp = reinterpret_cast<VirtioGpuCmd*>(ctx->cmd_resp->linear);
+
+    // We can configure bits of the response now. The size, and any message, will
+    // be updated later. This must be done even for the dummy 'op == 0' command.
+    cmd_resp->op = cmd->op;
+    cmd_resp->cmdSize = sizeof(*cmd_resp);
+
+    if (cmd->op == 0) {
+        // Send back a no-op response, just to keep the protocol in check
+        virgl_box box = {
+            .w = cmd_resp->cmdSize,
+            .h = 1,
+        };
+        sync_linear_to_iovec(ctx->cmd_resp, 0, &box);
+    } else {
+        // If the rcSetPuid command was already processed, this command will be
+        // processed by another thread. If not, the command data will be copied
+        // here and responded to when ctx->setFence() is called later.
+        ctx->submitCommand(buffer, bufSize);
+    }
+
+    g_last_submit_cmd_ctx = ctx;
+    return 0;
+}
+
+void virgl_renderer_get_cap_set(uint32_t set, uint32_t* max_ver, uint32_t* max_size) {
+    if (!max_ver || !max_size)
+        return;
+
+    printf("Request for caps version %u\n", set);
+
+    switch (set) {
+        case 1:
+            *max_ver = 1;
+            *max_size = sizeof(virgl_caps_v1);
+            break;
+        case 2:
+            *max_ver = 2;
+            *max_size = sizeof(virgl_caps_v2);
+            break;
+        default:
+            *max_ver = 0;
+            *max_size = 0;
+            break;
+    }
+}
+
+void virgl_renderer_fill_caps(uint32_t set, uint32_t, void* caps_) {
+    union virgl_caps* caps = static_cast<union virgl_caps*>(caps_);
+    EGLSurface old_read_surface, old_draw_surface;
+    GLfloat range[2] = { 0.0f, 0.0f };
+    bool fill_caps_v2 = false;
+    EGLContext old_context;
+    GLint max = 0;
+
+    if (!caps)
+        return;
+
+    // We don't need to handle caps yet, because our guest driver's features
+    // should be as close as possible to the host driver's. But maybe some day
+    // we'll support gallium shaders and the virgl control stream, so it seems
+    // like a good idea to set up the driver caps correctly..
+
+    // If this is broken, nothing will work properly
+    old_read_surface = s_egl.eglGetCurrentSurface(EGL_READ);
+    old_draw_surface = s_egl.eglGetCurrentSurface(EGL_DRAW);
+    old_context = s_egl.eglGetCurrentContext();
+    if (!s_egl.eglMakeCurrent(g_dpy, g_ctx0_surface, g_ctx0_surface, g_ctx0_es1)) {
+        printf("Failed to make ES1 context current\n");
+        return;
+    }
+
+    // Don't validate 'version' because it looks like this was misdesigned
+    // upstream and won't be set; instead, 'set' was bumped from 1->2.
+
+    switch (set) {
+        case 0:
+        case 1:
+            memset(caps, 0, sizeof(virgl_caps_v1));
+            caps->max_version = 1;
+            break;
+        case 2:
+            memset(caps, 0, sizeof(virgl_caps_v2));
+            caps->max_version = 2;
+            fill_caps_v2 = true;
+            break;
+        default:
+            caps->max_version = 0;
+            return;
+    }
+
+    if (fill_caps_v2) {
+        printf("Will probe and fill caps version 2.\n");
+    }
+
+    // Formats supported for textures
+
+    caps->v1.sampler.bitmask[0] = (1 << (VIRGL_FORMAT_B8G8R8A8_UNORM - (0 * 32))) |
+                                  (1 << (VIRGL_FORMAT_B5G6R5_UNORM - (0 * 32)));
+    caps->v1.sampler.bitmask[2] = (1 << (VIRGL_FORMAT_R8G8B8A8_UNORM - (2 * 32)));
+    caps->v1.sampler.bitmask[4] = (1 << (VIRGL_FORMAT_R8G8B8X8_UNORM - (4 * 32)));
+
+    // Formats supported for rendering
+
+    caps->v1.render.bitmask[0] = (1 << (VIRGL_FORMAT_B8G8R8A8_UNORM - (0 * 32))) |
+                                 (1 << (VIRGL_FORMAT_B5G6R5_UNORM - (0 * 32)));
+    caps->v1.render.bitmask[2] = (1 << (VIRGL_FORMAT_R8G8B8A8_UNORM - (2 * 32)));
+    caps->v1.render.bitmask[4] = (1 << (VIRGL_FORMAT_R8G8B8X8_UNORM - (4 * 32)));
+
+    // Could parse s_gles1.glGetString(GL_SHADING_LANGUAGE_VERSION, ...)?
+    caps->v1.glsl_level = 300;  // OpenGL ES GLSL 3.00
+
+    // Call with any API (v1, v3) bound
+
+    caps->v1.max_viewports = 1;
+
+    s_gles1.glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max);
+    caps->v1.max_render_targets = max;
+
+    s_gles1.glGetIntegerv(GL_MAX_SAMPLES_EXT, &max);
+    caps->v1.max_samples = max;
+
+    if (fill_caps_v2) {
+        s_gles1.glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
+        caps->v2.min_aliased_point_size = range[0];
+        caps->v2.max_aliased_point_size = range[1];
+
+        s_gles1.glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
+        caps->v2.min_aliased_line_width = range[0];
+        caps->v2.max_aliased_line_width = range[1];
+
+        // An extension, but everybody has it
+        s_gles1.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max);
+        caps->v2.max_vertex_attribs = max;
+
+        // Call with ES 1.0 bound *only*
+
+        s_gles1.glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, range);
+        caps->v2.min_smooth_point_size = range[0];
+        caps->v2.max_smooth_point_size = range[1];
+
+        s_gles1.glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range);
+        caps->v2.min_smooth_line_width = range[0];
+        caps->v2.max_smooth_line_width = range[1];
+    }
+
+    if (!s_egl.eglMakeCurrent(g_dpy, g_ctx0_surface, g_ctx0_surface, g_ctx0_es2)) {
+        s_egl.eglMakeCurrent(g_dpy, old_draw_surface, old_read_surface, old_context);
+        printf("Failed to make ES3 context current\n");
+        return;
+    }
+
+    // Call with ES 3.0 bound *only*
+
+    caps->v1.bset.primitive_restart = 1;
+    caps->v1.bset.seamless_cube_map = 1;
+    caps->v1.bset.occlusion_query = 1;
+    caps->v1.bset.instanceid = 1;
+    caps->v1.bset.ubo = 1;
+
+    s_gles1.glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &max);
+    caps->v1.max_texture_array_layers = max;
+
+    s_gles1.glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &max);
+    caps->v1.max_uniform_blocks = max + 1;
+
+    if (fill_caps_v2) {
+        s_gles1.glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps->v2.max_texture_lod_bias);
+
+        s_gles1.glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &max);
+        caps->v2.max_vertex_outputs = max / 4;
+
+        s_gles1.glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps->v2.min_texel_offset);
+        s_gles1.glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &caps->v2.max_texel_offset);
+
+        s_gles1.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &max);
+        caps->v2.uniform_buffer_offset_alignment = max;
+    }
+
+    // ES 2.0 extensions (fixme)
+
+    // Gallium compatibility; not usable currently.
+    caps->v1.prim_mask = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
+
+    if (!s_egl.eglMakeCurrent(g_dpy, old_draw_surface, old_read_surface, old_context)) {
+        printf("Failed to make no context current\n");
+    }
+}
+
+int virgl_renderer_create_fence(int client_fence_id, uint32_t cmd_type) {
+    switch (cmd_type) {
+        case VIRTIO_GPU_CMD_SUBMIT_3D:
+            if (g_last_submit_cmd_ctx) {
+                g_last_submit_cmd_ctx->setFence(client_fence_id);
+                break;
+            }
+            // Fall through
+        default: {
+            std::lock_guard<std::mutex> lk(g_fence_deque_mutex);
+            g_fence_deque.push_back(client_fence_id);
+            break;
+        }
+    }
+    return 0;
+}
+
+void virgl_renderer_force_ctx_0(void) {
+#ifdef QEMU_HARDWARE_GL_INTEROP
+    if (!g_ctx0_alt)
+        return;
+
+    if (g_cb->make_current(g_cookie, 0, g_ctx0_alt)) {
+        printf("Failed to make hardware GL context 0 current\n");
+        g_cb->destroy_gl_context(g_cookie, g_ctx0_alt);
+        g_ctx0_alt = nullptr;
+    }
+#endif
+}
+
+int virgl_renderer_resource_create(virgl_renderer_resource_create_args* args, iovec* iov,
+                                   uint32_t num_iovs) {
+    if (!args)
+        return EINVAL;
+
+    if (args->bind == VIRGL_RES_BIND_CURSOR) {
+        // Enforce limitation of current virtio-gpu-3d implementation
+        if (args->width != 64 || args->height != 64 || args->format != VIRGL_FORMAT_B8G8R8A8_UNORM)
+            return EINVAL;
+    }
+
+    assert(!Resource::map.count(args->handle) && "Can't insert same resource twice!");
+
+    Resource* res = new (std::nothrow) Resource(args, num_iovs, iov);
+    if (!res)
+        return ENOMEM;
+
+    printf("Creating Resource %u (num_iovs=%u)\n", args->handle, num_iovs);
+    return 0;
+}
+
+void virgl_renderer_resource_unref(uint32_t res_handle) {
+    std::map<uint32_t, Resource*>::iterator it;
+
+    it = Resource::map.find(res_handle);
+    if (it == Resource::map.end())
+        return;
+
+    Resource* res = it->second;
+
+    for (auto const& it : Context::map) {
+        Context const* ctx = it.second;
+
+        virgl_renderer_ctx_detach_resource(ctx->handle, res->args.handle);
+    }
+
+    assert(res->context_map.empty() && "Deleted resource was associated with contexts");
+
+    printf("Deleting Resource %u\n", res_handle);
+    delete res;
+}
+
+int virgl_renderer_resource_attach_iov(int res_handle, iovec* iov, int num_iovs) {
+    std::map<uint32_t, Resource*>::iterator it;
+
+    it = Resource::map.find((uint32_t)res_handle);
+    if (it == Resource::map.end())
+        return ENOENT;
+
+    Resource* res = it->second;
+
+    if (!res->iov) {
+        printf(
+            "Attaching backing store for Resource %d "
+            "(num_iovs=%d)\n",
+            res_handle, num_iovs);
+
+        res->num_iovs = num_iovs;
+        res->iov = iov;
+
+        res->reallocLinear();
+
+        // Assumes that when resources are attached, they contain junk, and we
+        // don't need to synchronize with the linear buffer
+    }
+
+    return 0;
+}
+
+void virgl_renderer_resource_detach_iov(int res_handle, iovec** iov, int* num_iovs) {
+    std::map<uint32_t, Resource*>::iterator it;
+
+    it = Resource::map.find((uint32_t)res_handle);
+    if (it == Resource::map.end())
+        return;
+
+    Resource* res = it->second;
+
+    printf("Detaching backing store for Resource %d\n", res_handle);
+
+    // Synchronize our linear buffer, if any, with the iovec that we are about
+    // to give up. Most likely this is not required, but it seems cleaner.
+    virgl_box box = {
+        .w = res->args.width,
+        .h = res->args.height,
+    };
+    sync_linear_to_iovec(res, 0, &box);
+
+    if (num_iovs)
+        *num_iovs = res->num_iovs;
+    res->num_iovs = 0U;
+
+    if (iov)
+        *iov = res->iov;
+    res->iov = nullptr;
+
+    res->reallocLinear();
+}
+
+int virgl_renderer_resource_get_info(int res_handle, virgl_renderer_resource_info* info) {
+    if (!info)
+        return EINVAL;
+
+    std::map<uint32_t, Resource*>::iterator it;
+
+    it = Resource::map.find((uint32_t)res_handle);
+    if (it == Resource::map.end())
+        return ENOENT;
+
+    Resource* res = it->second;
+
+    uint32_t bpp = 4U;
+    switch (res->args.format) {
+        case VIRGL_FORMAT_B8G8R8A8_UNORM:
+            info->drm_fourcc = DRM_FORMAT_BGRA8888;
+            break;
+        case VIRGL_FORMAT_B5G6R5_UNORM:
+            info->drm_fourcc = DRM_FORMAT_BGR565;
+            bpp = 2U;
+            break;
+        case VIRGL_FORMAT_R8G8B8A8_UNORM:
+            info->drm_fourcc = DRM_FORMAT_RGBA8888;
+            break;
+        case VIRGL_FORMAT_R8G8B8X8_UNORM:
+            info->drm_fourcc = DRM_FORMAT_RGBX8888;
+            break;
+        default:
+            return EINVAL;
+    }
+
+#ifdef QEMU_HARDWARE_GL_INTEROP
+    GLenum type = GL_UNSIGNED_BYTE;
+    GLenum format = GL_RGBA;
+    switch (res->args.format) {
+        case VIRGL_FORMAT_B8G8R8A8_UNORM:
+            format = 0x80E1;  // GL_BGRA
+            break;
+        case VIRGL_FORMAT_B5G6R5_UNORM:
+            type = GL_UNSIGNED_SHORT_5_6_5;
+            format = GL_RGB;
+            break;
+        case VIRGL_FORMAT_R8G8B8X8_UNORM:
+            format = GL_RGB;
+            break;
+    }
+
+    if (!res->tex_id) {
+        g_glGenTextures(1, &res->tex_id);
+        g_glBindTexture(GL_TEXTURE_2D, res->tex_id);
+        g_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        g_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        g_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        g_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    } else {
+        g_glBindTexture(GL_TEXTURE_2D, res->tex_id);
+    }
+
+    g_glPixelStorei(GL_UNPACK_ROW_LENGTH, ALIGN(res->args.width, 16));
+    g_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, res->args.width, res->args.height, 0, format, type,
+                   res->linear);
+#endif
+
+    info->stride = ALIGN(res->args.width * bpp, 16U);
+    info->virgl_format = res->args.format;
+    info->handle = res->args.handle;
+    info->height = res->args.height;
+    info->width = res->args.width;
+    info->depth = res->args.depth;
+    info->flags = res->args.flags;
+    info->tex_id = res->tex_id;
+
+    printf("Scanning out Resource %d\n", res_handle);
+    dump_global_state();
+
+    return 0;
+}
+
+int virgl_renderer_context_create(uint32_t handle, uint32_t nlen, const char* name) {
+    assert(!Context::map.count(handle) && "Can't insert same context twice!");
+
+    Context* ctx = new (std::nothrow) Context(handle, name, nlen, process_cmd, g_dpy);
+    if (!ctx)
+        return ENOMEM;
+
+    printf("Creating Context %u (%.*s)\n", handle, (int)nlen, name);
+    return 0;
+}
+
+void virgl_renderer_context_destroy(uint32_t handle) {
+    std::map<uint32_t, Context*>::iterator it;
+    it = Context::map.find(handle);
+    if (it == Context::map.end())
+        return;
+
+    Context* ctx = it->second;
+    printf("Destroying Context %u\n", handle);
+    delete ctx;
+}
+
+int virgl_renderer_transfer_read_iov(uint32_t handle, uint32_t, uint32_t, uint32_t, uint32_t,
+                                     virgl_box* box, uint64_t offset, iovec*, int) {
+    // stride, layer_stride and level are not set by minigbm, so don't try to
+    // validate them right now. iov and iovec_cnt are always passed as nullptr
+    // and 0 by qemu, so ignore those too
+
+    std::map<uint32_t, Resource*>::iterator it;
+    it = Resource::map.find((uint32_t)handle);
+    if (it == Resource::map.end())
+        return EINVAL;
+
+    return sync_linear_to_iovec(it->second, offset, box);
+}
+
+int virgl_renderer_transfer_write_iov(uint32_t handle, uint32_t, int, uint32_t, uint32_t,
+                                      virgl_box* box, uint64_t offset, iovec*, unsigned int) {
+    // stride, layer_stride and level are not set by minigbm, so don't try to
+    // validate them right now. iov and iovec_cnt are always passed as nullptr
+    // and 0 by qemu, so ignore those too
+
+    std::map<uint32_t, Resource*>::iterator it;
+    it = Resource::map.find((uint32_t)handle);
+    if (it == Resource::map.end())
+        return EINVAL;
+
+    return sync_iovec_to_linear(it->second, offset, box);
+}
+
+void virgl_renderer_ctx_attach_resource(int ctx_id, int res_handle) {
+    std::map<uint32_t, Context*>::iterator ctx_it;
+
+    ctx_it = Context::map.find((uint32_t)ctx_id);
+    if (ctx_it == Context::map.end())
+        return;
+
+    Context* ctx = ctx_it->second;
+
+    assert(!ctx->resource_map.count((uint32_t)res_handle) &&
+           "Can't attach resource to context twice!");
+
+    std::map<uint32_t, Resource*>::iterator res_it;
+
+    res_it = Resource::map.find((uint32_t)res_handle);
+    if (res_it == Resource::map.end())
+        return;
+
+    Resource* res = res_it->second;
+
+    printf("Attaching Resource %d to Context %d\n", res_handle, ctx_id);
+    res->context_map.emplace((uint32_t)ctx_id, ctx);
+    ctx->resource_map.emplace((uint32_t)res_handle, res);
+}
+
+void virgl_renderer_ctx_detach_resource(int ctx_id, int res_handle) {
+    std::map<uint32_t, Context*>::iterator ctx_it;
+
+    ctx_it = Context::map.find((uint32_t)ctx_id);
+    if (ctx_it == Context::map.end())
+        return;
+
+    Context* ctx = ctx_it->second;
+
+    std::map<uint32_t, Resource*>::iterator res_it;
+
+    res_it = ctx->resource_map.find((uint32_t)res_handle);
+    if (res_it == ctx->resource_map.end())
+        return;
+
+    Resource* res = res_it->second;
+
+    ctx_it = res->context_map.find((uint32_t)ctx_id);
+    if (ctx_it == res->context_map.end())
+        return;
+
+    printf("Detaching Resource %d from Context %d\n", res_handle, ctx_id);
+    if (ctx->cmd_resp && ctx->cmd_resp->args.handle == (uint32_t)res_handle)
+        ctx->cmd_resp = nullptr;
+    ctx->resource_map.erase(res_it);
+    res->context_map.erase(ctx_it);
+}
diff --git a/host/libs/virglrenderer/Android.bp b/host/libs/virglrenderer/Android.bp
new file mode 100644
index 0000000..7fd35d9
--- /dev/null
+++ b/host/libs/virglrenderer/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_library_host_shared {
+    name: "libvirglrenderer",
+    include_dirs: [
+        "external/libdrm",
+        "external/libdrm/include",
+        "device/generic/goldfish-opengl/system",
+    ],
+    local_include_dirs: [ "include" ],
+    srcs: [
+        "AVDVirglRenderer.cpp",
+        "ChecksumCalculator.cpp",
+        "GLESv1.cpp",
+        "GLESv1_dec/gles1_dec.cpp",
+        "GLESv3.cpp",
+        "GLESv3_dec/gles3_dec.cpp",
+        "Gralloc1.cpp",
+        "OpenGLESDispatch/EGLDispatch.cpp",
+        "OpenGLESDispatch/GLESv1Dispatch.cpp",
+        "OpenGLESDispatch/GLESv3Dispatch.cpp",
+        "RenderControl.cpp",
+        "renderControl_dec/renderControl_dec.cpp",
+    ],
+    cflags: ["-Wno-unused-parameter", "-DOPENGL_DEBUG_PRINTOUT"],
+    host_ldlibs: [ "-ldl" ],
+    version_script : "libvirglrenderer.lds",
+    defaults: [ "cuttlefish_host_only" ],
+}
diff --git a/host/libs/virglrenderer/ChecksumCalculator.cpp b/host/libs/virglrenderer/ChecksumCalculator.cpp
index 7bd82fc..b5d11c0 100644
--- a/host/libs/virglrenderer/ChecksumCalculator.cpp
+++ b/host/libs/virglrenderer/ChecksumCalculator.cpp
@@ -1,23 +1,21 @@
 /*
-* 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.
-*/
+ * 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 "ChecksumCalculator.h"
 
-#include "android/base/files/Stream.h"
-
 #include <string>
 #include <vector>
 
@@ -140,33 +138,3 @@
     revLen = (revLen & 0xaaaaaaaa) >> 1 | (revLen & 0x55555555) << 1;
     return revLen;
 }
-
-void ChecksumCalculator::save(android::base::Stream* stream) {
-    assert(!m_isEncodingChecksum);
-    switch (m_version) {
-    case 1:
-        assert(m_v1BufferTotalLength == 0);
-        break;
-    }
-
-    // Our checksum should never become > 255 bytes. Ever.
-    assert((uint8_t)m_checksumSize == m_checksumSize);
-    stream->putByte(m_checksumSize);
-    stream->putBe32(m_version);
-    stream->putBe32(m_numRead);
-    stream->putBe32(m_numWrite);
-}
-
-void ChecksumCalculator::load(android::base::Stream* stream) {
-    assert(!m_isEncodingChecksum);
-    switch (m_version) {
-    case 1:
-        assert(m_v1BufferTotalLength == 0);
-        break;
-    }
-
-    m_checksumSize = stream->getByte();
-    m_version = stream->getBe32();
-    m_numRead = stream->getBe32();
-    m_numWrite = stream->getBe32();
-}
diff --git a/host/libs/virglrenderer/ChecksumCalculator.h b/host/libs/virglrenderer/ChecksumCalculator.h
index df94403..8e8ce95 100644
--- a/host/libs/virglrenderer/ChecksumCalculator.h
+++ b/host/libs/virglrenderer/ChecksumCalculator.h
@@ -1,18 +1,18 @@
 /*
-* 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.
-*/
+ * 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.
+ */
 
 #pragma once
 
@@ -29,7 +29,11 @@
 #define LOG_CHECKSUMHELPER(x...)
 #endif
 
-namespace android { namespace base { class Stream; } }
+namespace android {
+namespace base {
+class Stream;
+}
+}  // namespace android
 
 // ChecksumCalculator adds checksum as an array of bytes to GL pipe communication, which
 // size depends on the protocol version. Each pipe should use one ChecksumCalculator.
@@ -124,11 +128,13 @@
 // }
 
 class ChecksumCalculator {
-public:
+  public:
     static constexpr size_t kMaxChecksumLength = 8;
 
     // Get and set current checksum version
-    uint32_t getVersion() const { return m_version; }
+    uint32_t getVersion() const {
+        return m_version;
+    }
     // Call setVersion to set a checksum version. It should be called before
     // addBuffer(), writeChecksum() and validate(). And it should be called
     // exact once per rendering thread if both host and guest support checksum.
@@ -146,7 +152,9 @@
     static const char* getMaxVersionStrPrefix();
 
     // Size of checksum in the current version
-    size_t checksumByteSize() const { return m_checksumSize; }
+    size_t checksumByteSize() const {
+        return m_checksumSize;
+    }
 
     // Update the current checksum value from the data
     // at |buf| of |bufLen| bytes. Once all buffers
@@ -169,11 +177,7 @@
     // Will reset the list of buffers by calling resetChecksum.
     bool validate(const void* expectedChecksum, size_t expectedChecksumLen);
 
-    // Snapshot support.
-    void save(android::base::Stream* stream);
-    void load(android::base::Stream* stream);
-
-private:
+  private:
     static constexpr size_t kVersion1ChecksumSize = 8;  // 2 x uint32_t
 
     static_assert(kVersion1ChecksumSize <= kMaxChecksumLength,
diff --git a/host/libs/virglrenderer/ChecksumCalculatorThreadInfo.h b/host/libs/virglrenderer/ChecksumCalculatorThreadInfo.h
index e22d3ba..51f8e1c 100644
--- a/host/libs/virglrenderer/ChecksumCalculatorThreadInfo.h
+++ b/host/libs/virglrenderer/ChecksumCalculatorThreadInfo.h
@@ -1,60 +1,45 @@
 /*
-* 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.
-*/
+ * Copyright (C) 2018 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.
+ */
 
 #pragma once
 
 #include "ChecksumCalculator.h"
 
-// ChecksumCalculatorThreadInfo is the class that makes ChecksumCalculator
-// thread-safe. On the host, please only use ChecksumCalculator through this
-// class.
+#include <stdio.h>
+
+// NOTE: This fork of ChecksumCalculatorThreadInfo is *not* thread safe
 
 class ChecksumCalculatorThreadInfo {
-public:
-    ChecksumCalculatorThreadInfo();
-    ~ChecksumCalculatorThreadInfo();
-
-    ChecksumCalculator& get();
-
-    static bool setVersion(uint32_t version);
-
-    static uint32_t getMaxVersion();
-    static const char* getMaxVersionString() {
-        return ChecksumCalculator::getMaxVersionStr();
+  public:
+    static bool writeChecksum(ChecksumCalculator* calc, void* buf, size_t bufLen,
+                              void* outputChecksum, size_t outputChecksumLen) {
+        calc->addBuffer(buf, bufLen);
+        return calc->writeChecksum(outputChecksum, outputChecksumLen);
     }
 
-    static bool writeChecksum(ChecksumCalculator* calc,
-                              void* buf,
-                              size_t bufLen,
-                              void* outputChecksum,
-                              size_t outputChecksumLen);
+    static bool validate(ChecksumCalculator* calc, void* buf, size_t bufLen, void* checksum,
+                         size_t checksumLen) {
+        calc->addBuffer(buf, bufLen);
+        return calc->validate(checksum, checksumLen);
+    }
 
-    static bool validate(ChecksumCalculator* calc,
-                         void* buf,
-                         size_t bufLen,
-                         void* checksum,
-                         size_t checksumLen);
-
-    static void validOrDie(ChecksumCalculator* calc,
-                           void* buf,
-                           size_t bufLen,
-                           void* checksum,
-                           size_t checksumLen,
-                           const char* message);
-
-private:
-    ChecksumCalculator m_protocol;
+    static void validOrDie(ChecksumCalculator* calc, void* buf, size_t bufLen, void* checksum,
+                           size_t checksumLen, const char* message) {
+        if (!validate(calc, buf, bufLen, checksum, checksumLen)) {
+            printf("%s\n", message);
+        }
+    }
 };
diff --git a/host/libs/virglrenderer/Context.h b/host/libs/virglrenderer/Context.h
new file mode 100644
index 0000000..53c5488
--- /dev/null
+++ b/host/libs/virglrenderer/Context.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#undef NDEBUG
+
+#include <cassert>
+#include <condition_variable>
+#include <cstdint>
+#include <map>
+#include <mutex>
+#include <string>
+#include <thread>
+
+#include "GLESv1.h"
+#include "GLESv3.h"
+#include "RenderControl.h"
+#include "Resource.h"
+
+struct EglContext;
+struct Context;
+
+typedef void (*PFNSUBMITCMD)(Context*, char*, size_t, int);
+
+struct Context {
+    static std::map<uint32_t, Context*> map;
+
+    Context(uint32_t handle_, const char* name_, uint32_t nlen_, PFNSUBMITCMD pfnProcessCmd_,
+            EGLDisplay dpy_)
+        : render_control(this, dpy_), worker(), name(std::string(name_, nlen_)), handle(handle_),
+          pfnProcessCmd(pfnProcessCmd_) {
+        map.emplace(handle, this);
+        reset();
+    }
+
+    ~Context() {
+        {
+            std::lock_guard<std::mutex> lk(m);
+            killWorker = true;
+        }
+        cv.notify_one();
+        if (worker.joinable())
+            worker.join();
+        map.erase(handle);
+    }
+
+    Context* bind(EglContext* ctx_) {
+        for (auto const& it : Context::map) {
+            Context* ctx = it.second;
+            if (ctx == this)
+                continue;
+            if (ctx->ctx == ctx_)
+                return ctx;
+        }
+        ctx = ctx_;
+        return nullptr;
+    }
+
+    void unbind() {
+        ctx = nullptr;
+    }
+
+    void setPidTid(int pid_, int tid_) {
+        if (pid != pid_ && tid != tid_) {
+            assert(!worker.joinable() && "Changing pid/tid is not allowed");
+            worker = std::thread(&Context::worker_func, this);
+        }
+        pid = pid_;
+        tid = tid_;
+    }
+
+    void submitCommand(void* buf, size_t bufSize) {
+        char* cmdBufCopy = new char[bufSize];
+        memcpy(cmdBufCopy, buf, bufSize);
+        {
+            std::lock_guard<std::mutex> lk(m);
+            cmdBufSize = bufSize;
+            cmdBuf = cmdBufCopy;
+        }
+        cv.notify_one();
+    }
+
+    void setFence(int fence_) {
+        {
+            std::lock_guard<std::mutex> lk(m);
+            fence = fence_;
+            if (!worker.joinable())
+                processCmd();
+        }
+        cv.notify_one();
+    }
+
+    std::map<uint32_t, Resource*> resource_map;
+    ChecksumCalculator checksum_calc;
+    RenderControl render_control;
+    Resource* cmd_resp = nullptr;
+    EglContext* ctx = nullptr;
+    std::thread worker;
+    std::string name;
+    uint32_t handle;
+    GLESv1 gles1;
+    GLESv3 gles3;
+    int pid = 0;
+    int tid = 0;
+
+  private:
+    std::condition_variable cv;
+    PFNSUBMITCMD pfnProcessCmd;
+    bool killWorker = false;
+    size_t cmdBufSize;
+    char* cmdBuf;
+    std::mutex m;
+    int fence;
+
+    void reset() {
+        cmdBuf = nullptr;
+        cmdBufSize = 0U;
+        fence = 0;
+    }
+
+    void worker_func() {
+        while (!killWorker) {
+            std::unique_lock<std::mutex> lk(m);
+            cv.wait(lk, [this] { return killWorker || (cmdBuf && fence); });
+            if (!killWorker)
+                processCmd();
+            lk.unlock();
+        }
+    }
+
+    void processCmd() {
+        pfnProcessCmd(this, cmdBuf, cmdBufSize, fence);
+        delete cmdBuf;
+        reset();
+    }
+};
diff --git a/host/libs/virglrenderer/EglConfig.h b/host/libs/virglrenderer/EglConfig.h
new file mode 100644
index 0000000..3b5cd2b
--- /dev/null
+++ b/host/libs/virglrenderer/EglConfig.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+typedef EGLBoolean (*PFNEGLGETCONFIGATTRIB)(EGLDisplay, EGLConfig, EGLint, EGLint*);
+
+struct EglConfig {
+    static std::vector<EglConfig*> vec;
+
+    // clang-format off
+    static constexpr EGLint kAttribs[] = {
+        EGL_DEPTH_SIZE,
+        EGL_STENCIL_SIZE,
+        EGL_RENDERABLE_TYPE,
+        EGL_SURFACE_TYPE,
+        EGL_CONFIG_ID,
+        EGL_BUFFER_SIZE,
+        EGL_ALPHA_SIZE,
+        EGL_BLUE_SIZE,
+        EGL_GREEN_SIZE,
+        EGL_RED_SIZE,
+        EGL_CONFIG_CAVEAT,
+        EGL_LEVEL,
+        EGL_MAX_PBUFFER_HEIGHT,
+        EGL_MAX_PBUFFER_PIXELS,
+        EGL_MAX_PBUFFER_WIDTH,
+        EGL_NATIVE_RENDERABLE,
+        EGL_NATIVE_VISUAL_ID,
+        EGL_NATIVE_VISUAL_TYPE,
+        0x3030, // EGL_PRESERVED_RESOURCES
+        EGL_SAMPLES,
+        EGL_SAMPLE_BUFFERS,
+        EGL_TRANSPARENT_TYPE,
+        EGL_TRANSPARENT_BLUE_VALUE,
+        EGL_TRANSPARENT_GREEN_VALUE,
+        EGL_TRANSPARENT_RED_VALUE,
+        EGL_BIND_TO_TEXTURE_RGB,
+        EGL_BIND_TO_TEXTURE_RGBA,
+        EGL_MIN_SWAP_INTERVAL,
+        EGL_MAX_SWAP_INTERVAL,
+        EGL_LUMINANCE_SIZE,
+        EGL_ALPHA_MASK_SIZE,
+        EGL_COLOR_BUFFER_TYPE,
+        //EGL_MATCH_NATIVE_PIXMAP,
+        EGL_RECORDABLE_ANDROID,
+        EGL_CONFORMANT
+    };
+    // clang-format on
+
+    static constexpr size_t kNumAttribs = sizeof(kAttribs) / sizeof(kAttribs[0]);
+
+    EglConfig(EGLDisplay dpy, EGLConfig config_, PFNEGLGETCONFIGATTRIB pfnEglGetConfigAttrib)
+        : config(config_) {
+        for (size_t a = 0; a < kNumAttribs; a++) {
+            if (!pfnEglGetConfigAttrib(dpy, config, kAttribs[a], &attribs[a]))
+                attribs[a] = 0;
+        }
+        vec.push_back(this);
+    }
+
+    ~EglConfig() {
+        for (size_t i = 0; i < EglConfig::vec.size(); i++) {
+            if (vec[i] == this) {
+                vec.erase(vec.begin() + i);
+                break;
+            }
+        }
+    }
+
+    EGLint attribs[kNumAttribs];
+    EGLConfig config;
+};
diff --git a/host/libs/virglrenderer/EglContext.h b/host/libs/virglrenderer/EglContext.h
new file mode 100644
index 0000000..7283c08
--- /dev/null
+++ b/host/libs/virglrenderer/EglContext.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <map>
+
+#include <EGL/egl.h>
+
+struct EglContext {
+    enum GLESApi {
+        GLESApi_CM = 1,
+        GLESApi_2 = 2,
+        GLESApi_3_0 = 3,
+        GLESApi_3_1 = 4,
+    };
+
+    static std::map<uint32_t, EglContext*> map;
+    static uint32_t nextId;
+
+    EglContext(EGLContext context_, uint32_t ctx_, GLESApi api_)
+        : create_ctx(ctx_), context(context_), api(api_), id(nextId++) {
+        map.emplace(id, this);
+    }
+
+    ~EglContext() {
+        map.erase(id);
+    }
+
+    EglContext* bind(uint32_t ctx_) {
+        for (auto const& it : EglContext::map) {
+            EglContext* ctx = it.second;
+            if (ctx == this)
+                continue;
+            if (ctx->bound_ctx == ctx_)
+                return ctx;
+        }
+        bound_ctx = ctx_;
+        return nullptr;
+    }
+
+    void unbind() {
+        bound_ctx = 0U;
+    }
+
+    bool disposable() {
+        return context == EGL_NO_CONTEXT && bound_ctx == 0U;
+    }
+
+    uint32_t create_ctx;
+    EGLContext context;
+    enum GLESApi api;
+    uint32_t id;
+
+  private:
+    uint32_t bound_ctx = 0U;
+};
diff --git a/host/libs/virglrenderer/EglImage.h b/host/libs/virglrenderer/EglImage.h
new file mode 100644
index 0000000..09b968c
--- /dev/null
+++ b/host/libs/virglrenderer/EglImage.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <map>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+typedef EGLBoolean (*PFNEGLDESTROYIMAGEKHR)(EGLDisplay, EGLImageKHR);
+
+struct EglImage {
+    static std::map<uint32_t, EglImage*> map;
+    static uint32_t nextId;
+
+    EglImage(EGLDisplay dpy_, EGLImageKHR image_, PFNEGLDESTROYIMAGEKHR pfnEglDestroyImageKHR_)
+        : pfnEglDestroyImageKHR(pfnEglDestroyImageKHR_), image(image_), dpy(dpy_), id(nextId++) {
+        map.emplace(id, this);
+    }
+
+    ~EglImage() {
+        pfnEglDestroyImageKHR(dpy, image);
+        map.erase(id);
+    }
+
+    PFNEGLDESTROYIMAGEKHR pfnEglDestroyImageKHR;
+    EGLImageKHR image;
+    EGLDisplay dpy;
+    uint32_t id;
+};
diff --git a/host/libs/virglrenderer/EglSurface.h b/host/libs/virglrenderer/EglSurface.h
new file mode 100644
index 0000000..4bb880d
--- /dev/null
+++ b/host/libs/virglrenderer/EglSurface.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <map>
+
+#include <EGL/egl.h>
+
+struct ANativeWindow;
+
+struct EglSurface {
+    static std::map<uint32_t, EglSurface*> map;
+    static uint32_t nextId;
+
+    EglSurface(EGLConfig config_, uint32_t ctx_, uint32_t width_, uint32_t height_)
+        : create_ctx(ctx_), config(config_), height(height_), width(width_), id(nextId++) {
+        map.emplace(id, this);
+    }
+
+    ~EglSurface() {
+        map.erase(id);
+    }
+
+    EglSurface* bind(uint32_t ctx_, bool read_) {
+        for (auto const& it : EglSurface::map) {
+            EglSurface* sur = it.second;
+            if (sur == this)
+                continue;
+            if (sur->bound_ctx == ctx_) {
+                if (read_ && sur->read)
+                    return sur;
+                if (!read_ && sur->draw)
+                    return sur;
+            }
+        }
+        if (read_) {
+            read = true;
+        } else {
+            draw = true;
+        }
+        bound_ctx = ctx_;
+        return nullptr;
+    }
+
+    void unbind(bool read_) {
+        if (read || draw) {
+            if (read_)
+                read = false;
+            else
+                draw = false;
+            if (read || draw)
+                return;
+            bound_ctx = 0U;
+        }
+        return;
+    }
+
+    bool disposable() {
+        return surface == EGL_NO_SURFACE && bound_ctx == 0U;
+    }
+
+    EGLSurface surface = EGL_NO_SURFACE;
+    ANativeWindow* window = nullptr;
+    uint32_t create_ctx;
+    EGLConfig config;
+    uint32_t height;
+    uint32_t width;
+    uint32_t id;
+
+  private:
+    uint32_t bound_ctx = 0U;
+    bool draw = false;
+    bool read = false;
+};
diff --git a/host/libs/virglrenderer/EglSync.h b/host/libs/virglrenderer/EglSync.h
new file mode 100644
index 0000000..8dda713
--- /dev/null
+++ b/host/libs/virglrenderer/EglSync.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <map>
+
+#include <EGL/egl.h>
+
+struct EglSync {
+    static std::map<uint64_t, EglSync*> map;
+    static uint64_t nextId;
+
+    EglSync(EGLSyncKHR sync_) : sync(sync_), id(nextId++) {
+        map.emplace(id, this);
+    }
+
+    ~EglSync() {
+        map.erase(id);
+    }
+
+    EGLSyncKHR sync;
+    uint64_t id;
+};
diff --git a/host/libs/virglrenderer/GLESv1.cpp b/host/libs/virglrenderer/GLESv1.cpp
new file mode 100644
index 0000000..17a7ae4
--- /dev/null
+++ b/host/libs/virglrenderer/GLESv1.cpp
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2018 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 <OpenGLESDispatch/GLESv1Dispatch.h>
+
+#include "GLESv1.h"
+
+// Stubs (common)
+
+static void glDeleteFencesNV(GLsizei, const GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glDisableDriverControlQCOM(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glDiscardFramebufferEXT(GLenum, GLsizei, const GLenum*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glEnableDriverControlQCOM(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glEndTilingQCOM(GLbitfield) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetBufferPointervQCOM(GLenum, GLvoid**) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetBuffersQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetFramebuffersQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetProgramBinarySourceQCOM(GLuint, GLenum, GLchar*, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetProgramsQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetRenderbuffersQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetShadersQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetTexLevelParameterivQCOM(GLuint, GLenum, GLint, GLenum, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetTexSubImageQCOM(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei,
+                                    GLenum, GLenum, GLvoid*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetTexturesQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLboolean glExtIsProgramBinaryQCOM(GLuint) {
+    printf("%s: not implemented\n", __func__);
+    return GL_FALSE;
+}
+
+static void glExtTexObjectStateOverrideiQCOM(GLenum, GLenum, GLint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glFinishFenceNV(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glFramebufferTexture2DMultisampleIMG(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGenFencesNV(GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetDriverControlsQCOM(GLint*, GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetDriverControlStringQCOM(GLuint, GLsizei, GLsizei*, GLchar*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetFenceivNV(GLuint, GLenum, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLboolean glIsFenceNV(GLuint) {
+    printf("%s: not implemented\n", __func__);
+    return GL_FALSE;
+}
+
+static void* glMapBufferOES(GLenum, GLenum) {
+    printf("%s: not implemented\n", __func__);
+    return nullptr;
+}
+
+static void glMultiDrawArraysEXT(GLenum, const GLint*, const GLsizei*, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glMultiDrawElementsEXT(GLenum, const GLsizei*, GLenum, const GLvoid* const*, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glRenderbufferStorageMultisampleIMG(GLenum, GLsizei, GLenum, GLsizei, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glSetFenceNV(GLuint, GLenum) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glStartTilingQCOM(GLuint, GLuint, GLuint, GLuint, GLbitfield) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLboolean glTestFenceNV(GLuint) {
+    printf("%s: not implemented\n", __func__);
+    return GL_FALSE;
+}
+
+// Stubs (ES 1.1)
+
+static void glBindVertexArrayOES(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glCurrentPaletteMatrixOES(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glDeleteVertexArraysOES(GLsizei, const GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGenVertexArraysOES(GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetBufferPointervOES(GLenum, GLenum, GLvoid**) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetTexGenfvOES(GLenum, GLenum, GLfloat*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetTexGenivOES(GLenum, GLenum, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetTexGenxvOES(GLenum, GLenum, GLfixed*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLboolean glIsVertexArrayOES(GLuint) {
+    printf("%s: not implemented\n", __func__);
+    return GL_FALSE;
+}
+
+static void glLoadPaletteFromModelViewMatrixOES() {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glMatrixIndexPointerData(GLint, GLenum, GLsizei, void*, GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glMatrixIndexPointerOffset(GLint, GLenum, GLsizei, GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glMultiDrawArraysSUN(GLenum, GLint*, GLsizei*, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glMultiDrawElementsSUN(GLenum, const GLsizei*, GLenum, const GLvoid**, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLbitfield glQueryMatrixxOES(GLfixed*, GLint*) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static void glTexGenfOES(GLenum, GLenum, GLfloat) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glTexGenfvOES(GLenum, GLenum, const GLfloat*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glTexGeniOES(GLenum, GLenum, GLint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glTexGenivOES(GLenum, GLenum, const GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glTexGenxOES(GLenum, GLenum, GLfixed) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glTexGenxvOES(GLenum, GLenum, const GLfixed*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLboolean glUnmapBufferOES(GLenum) {
+    printf("%s: not implemented\n", __func__);
+    return GL_FALSE;
+}
+
+static void glWeightPointerData(GLint, GLenum, GLsizei, void*, GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glWeightPointerOffset(GLint, GLenum, GLsizei, GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+// Non-stubs (common)
+
+static void glDrawElementsData(GLenum mode, GLsizei count, GLenum type, void* indices, GLuint) {
+    s_gles1.glDrawElements(mode, count, type, indices);
+}
+
+static void glDrawElementsOffset(GLenum mode, GLsizei count, GLenum type, GLuint offset) {
+    s_gles1.glDrawElements(mode, count, type, reinterpret_cast<const GLvoid*>(offset));
+}
+
+static GLint glFinishRoundTrip() {
+    s_gles1.glFinish();
+    return 0;
+}
+
+static void glGetCompressedTextureFormats(int count, GLint* formats) {
+    int nFormats;
+    s_gles1.glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &nFormats);
+    if (nFormats <= count)
+        s_gles1.glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
+}
+
+// Non-stubs (ES 1.1)
+
+static void glColorPointerData(GLint size, GLenum type, GLsizei, void* data, GLuint) {
+    s_gles1.glColorPointer(size, type, 0, data);
+}
+
+static void glColorPointerOffset(GLint size, GLenum type, GLsizei, GLuint offset) {
+    s_gles1.glColorPointer(size, type, 0, reinterpret_cast<GLvoid*>(offset));
+}
+
+static void glNormalPointerData(GLenum type, GLsizei, void* data, GLuint) {
+    s_gles1.glNormalPointer(type, 0, data);
+}
+
+static void glNormalPointerOffset(GLenum type, GLsizei, GLuint offset) {
+    s_gles1.glNormalPointer(type, 0, reinterpret_cast<GLvoid*>(offset));
+}
+
+static void glPointSizePointerData(GLenum type, GLsizei, void* data, GLuint) {
+    s_gles1.glPointSizePointerOES(type, 0, data);
+}
+
+static void glPointSizePointerOffset(GLenum type, GLsizei, GLuint offset) {
+    s_gles1.glPointSizePointerOES(type, 0, reinterpret_cast<GLvoid*>(offset));
+}
+
+static void glTexCoordPointerData(GLint, GLint size, GLenum type, GLsizei, void* data, GLuint) {
+    // FIXME: unit?
+    s_gles1.glTexCoordPointer(size, type, 0, data);
+}
+
+static void glTexCoordPointerOffset(GLint size, GLenum type, GLsizei, GLuint offset) {
+    s_gles1.glTexCoordPointer(size, type, 0, reinterpret_cast<GLvoid*>(offset));
+}
+
+static void glVertexPointerData(GLint size, GLenum type, GLsizei, void* data, GLuint) {
+    s_gles1.glVertexPointer(size, type, 0, data);
+}
+
+static void glVertexPointerOffset(GLint size, GLenum type, GLsizei, GLuint offset) {
+    s_gles1.glVertexPointer(size, type, 0, reinterpret_cast<GLvoid*>(offset));
+}
+
+#define KNIT(return_type, function_name, signature, callargs) function_name = s_gles1.function_name;
+
+GLESv1::GLESv1() {
+    LIST_GLES1_FUNCTIONS(KNIT, KNIT)
+
+    // Remap some ES 1.0 extensions that become core in ES 1.1
+    glAlphaFuncxOES = glAlphaFuncx;
+    glClearColorxOES = glClearColorx;
+    glClearDepthfOES = glClearDepthf;
+    glClearDepthxOES = glClearDepthx;
+    glClipPlanefIMG = glClipPlanef;
+    glClipPlanefOES = glClipPlanef;
+    glClipPlanexIMG = glClipPlanex;
+    glClipPlanexOES = glClipPlanex;
+    glColor4xOES = glColor4x;
+    glDepthRangefOES = glDepthRangef;
+    glDepthRangexOES = glDepthRangex;
+    glFogxOES = glFogx;
+    glFogxvOES = glFogxv;
+    glFrustumfOES = glFrustumf;
+    glFrustumxOES = glFrustumx;
+    glGetClipPlanefOES = glGetClipPlanef;
+    glGetClipPlanexOES = glGetClipPlanex;
+    glGetFixedvOES = glGetFixedv;
+    glGetLightxvOES = glGetLightxv;
+    glGetMaterialxvOES = glGetMaterialxv;
+    glGetTexEnvxvOES = glGetTexEnvxv;
+    glGetTexParameterxvOES = glGetTexParameterxv;
+    glLightModelxOES = glLightModelx;
+    glLightModelxvOES = glLightModelxv;
+    glLightxOES = glLightx;
+    glLightxvOES = glLightxv;
+    glLineWidthxOES = glLineWidthx;
+    glLoadMatrixxOES = glLoadMatrixx;
+    glMaterialxOES = glMaterialx;
+    glMaterialxvOES = glMaterialxv;
+    glMultiTexCoord4xOES = glMultiTexCoord4x;
+    glMultMatrixxOES = glMultMatrixx;
+    glNormal3xOES = glNormal3x;
+    glOrthofOES = glOrthof;
+    glOrthoxOES = glOrthox;
+    glPointParameterxOES = glPointParameterx;
+    glPointParameterxvOES = glPointParameterxv;
+    glPointSizexOES = glPointSizex;
+    glPolygonOffsetxOES = glPolygonOffsetx;
+    glRotatexOES = glRotatex;
+    glSampleCoveragexOES = glSampleCoveragex;
+    glScalexOES = glScalex;
+    glTexEnvxOES = glTexEnvx;
+    glTexEnvxvOES = glTexEnvxv;
+    glTexParameterxOES = glTexParameterx;
+    glTexParameterxvOES = glTexParameterxv;
+    glTranslatexOES = glTranslatex;
+
+    // Entrypoints requiring custom wrappers (common)
+    glDrawElementsData = ::glDrawElementsData;
+    glDrawElementsOffset = ::glDrawElementsOffset;
+    glFinishRoundTrip = ::glFinishRoundTrip;
+    glGetCompressedTextureFormats = ::glGetCompressedTextureFormats;
+
+    // Entrypoints requiring custom wrappers (ES 1.1)
+    glColorPointerData = ::glColorPointerData;
+    glColorPointerOffset = ::glColorPointerOffset;
+    glNormalPointerData = ::glNormalPointerData;
+    glNormalPointerOffset = ::glNormalPointerOffset;
+    glPointSizePointerData = ::glPointSizePointerData;
+    glPointSizePointerOffset = ::glPointSizePointerOffset;
+    glTexCoordPointerData = ::glTexCoordPointerData;
+    glTexCoordPointerOffset = ::glTexCoordPointerOffset;
+    glVertexPointerData = ::glVertexPointerData;
+    glVertexPointerOffset = ::glVertexPointerOffset;
+
+    // Stub some extensions we will never implement (common)
+    glDeleteFencesNV = ::glDeleteFencesNV;
+    glDisableDriverControlQCOM = ::glDisableDriverControlQCOM;
+    glDiscardFramebufferEXT = ::glDiscardFramebufferEXT;
+    glEnableDriverControlQCOM = ::glEnableDriverControlQCOM;
+    glEndTilingQCOM = ::glEndTilingQCOM;
+    glExtGetBufferPointervQCOM = ::glExtGetBufferPointervQCOM;
+    glExtGetBuffersQCOM = ::glExtGetBuffersQCOM;
+    glExtGetFramebuffersQCOM = ::glExtGetFramebuffersQCOM;
+    glExtGetProgramBinarySourceQCOM = ::glExtGetProgramBinarySourceQCOM;
+    glExtGetProgramsQCOM = ::glExtGetProgramsQCOM;
+    glExtGetRenderbuffersQCOM = ::glExtGetRenderbuffersQCOM;
+    glExtGetShadersQCOM = ::glExtGetShadersQCOM;
+    glExtGetTexLevelParameterivQCOM = ::glExtGetTexLevelParameterivQCOM;
+    glExtGetTexSubImageQCOM = ::glExtGetTexSubImageQCOM;
+    glExtGetTexturesQCOM = ::glExtGetTexturesQCOM;
+    glExtIsProgramBinaryQCOM = ::glExtIsProgramBinaryQCOM;
+    glExtTexObjectStateOverrideiQCOM = ::glExtTexObjectStateOverrideiQCOM;
+    glFinishFenceNV = ::glFinishFenceNV;
+    glFramebufferTexture2DMultisampleIMG = ::glFramebufferTexture2DMultisampleIMG;
+    glGenFencesNV = ::glGenFencesNV;
+    glGetDriverControlsQCOM = ::glGetDriverControlsQCOM;
+    glGetDriverControlStringQCOM = ::glGetDriverControlStringQCOM;
+    glGetFenceivNV = ::glGetFenceivNV;
+    glIsFenceNV = ::glIsFenceNV;
+    glMapBufferOES = ::glMapBufferOES;
+    glMultiDrawArraysEXT = ::glMultiDrawArraysEXT;
+    glMultiDrawElementsEXT = ::glMultiDrawElementsEXT;
+    glRenderbufferStorageMultisampleIMG = ::glRenderbufferStorageMultisampleIMG;
+    glSetFenceNV = ::glSetFenceNV;
+    glStartTilingQCOM = ::glStartTilingQCOM;
+    glTestFenceNV = ::glTestFenceNV;
+
+    // Stub some extensions we will never implement (ES 1.1)
+    glBindVertexArrayOES = ::glBindVertexArrayOES;
+    glCurrentPaletteMatrixOES = ::glCurrentPaletteMatrixOES;
+    glDeleteVertexArraysOES = ::glDeleteVertexArraysOES;
+    glGenVertexArraysOES = ::glGenVertexArraysOES;
+    glGetBufferPointervOES = ::glGetBufferPointervOES;
+    glGetTexGenfvOES = ::glGetTexGenfvOES;
+    glGetTexGenivOES = ::glGetTexGenivOES;
+    glGetTexGenxvOES = ::glGetTexGenxvOES;
+    glIsVertexArrayOES = ::glIsVertexArrayOES;
+    glLoadPaletteFromModelViewMatrixOES = ::glLoadPaletteFromModelViewMatrixOES;
+    glMatrixIndexPointerData = ::glMatrixIndexPointerData;
+    glMatrixIndexPointerOffset = ::glMatrixIndexPointerOffset;
+    glMultiDrawArraysSUN = ::glMultiDrawArraysSUN;
+    glMultiDrawElementsSUN = ::glMultiDrawElementsSUN;
+    glQueryMatrixxOES = ::glQueryMatrixxOES;
+    glTexGenfOES = ::glTexGenfOES;
+    glTexGenfvOES = ::glTexGenfvOES;
+    glTexGeniOES = ::glTexGeniOES;
+    glTexGenivOES = ::glTexGenivOES;
+    glTexGenxOES = ::glTexGenxOES;
+    glTexGenxvOES = ::glTexGenxvOES;
+    glUnmapBufferOES = ::glUnmapBufferOES;
+    glWeightPointerData = ::glWeightPointerData;
+    glWeightPointerOffset = ::glWeightPointerOffset;
+}
diff --git a/host/libs/virglrenderer/GLESv1.h b/host/libs/virglrenderer/GLESv1.h
new file mode 100644
index 0000000..f8b9073
--- /dev/null
+++ b/host/libs/virglrenderer/GLESv1.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include "GLESv1_dec/gles1_dec.h"
+
+struct GLESv1 : public gles1_decoder_context_t {
+    GLESv1();
+};
diff --git a/host/libs/virglrenderer/GLESv1_dec/gles1.attrib b/host/libs/virglrenderer/GLESv1_dec/gles1.attrib
index 3cbc9d3..a1f1ee7 100644
--- a/host/libs/virglrenderer/GLESv1_dec/gles1.attrib
+++ b/host/libs/virglrenderer/GLESv1_dec/gles1.attrib
@@ -1,704 +1,444 @@
 GLOBAL
-	base_opcode 1024
-	encoder_headers "glUtils.h" "GLEncoderUtils.h"
-	
-#void glClipPlanef(GLenum plane, GLfloat *equation)
+    base_opcode 1024
+
 glClipPlanef
-  dir equation in
-	len equation (4 * sizeof(float))
+    dir equation in
+    len equation (4 * sizeof(float))
 
-#void glFogfv(GLenum pname, GLfloat *params)
-glFogfv
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glGetFloatv(GLenum pname, GLfloat *params)
 glGetFloatv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
+    dir params out
 
-#void glGetLightfv(GLenum light, GLenum pname, GLfloat *params)
 glGetLightfv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
+    dir params out
 
-#void glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params)
 glGetMaterialfv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
+    dir params out
 
-#void glGetTexEnvfv(GLenum env, GLenum pname, GLfloat *params)
 glGetTexEnvfv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
+    dir params out
 
-#void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
 glGetTexParameterfv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
+    dir params out
 
-#void glLightModelfv(GLenum pname, GLfloat *params)
-glLightModelfv
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glLightfv(GLenum light, GLenum pname, GLfloat *params)
-glLightfv
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glLoadMatrixf(GLfloat *m)
 glLoadMatrixf
-	len m (16 * sizeof(GLfloat))
+    len m (16 * sizeof(GLfloat))
 
-#void glMaterialfv(GLenum face, GLenum pname, GLfloat *params)
-glMaterialfv
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glMultMatrixf(GLfloat *m)
 glMultMatrixf
-	len m (16 * sizeof(GLfloat))
+    len m (16 * sizeof(GLfloat))
 
-#void glPointParameterfv(GLenum pname, GLfloat *params)
-glPointParameterfv
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glTexEnvfv(GLenum target, GLenum pname, GLfloat *params)
-glTexEnvfv
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
-glTexParameterfv
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glBufferData(GLenum target, GLsizeiptr size, GLvoid *data, GLenum usage)
 glBufferData
-	len data size
-	var_flag data nullAllowed
-
-#void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data)
-glBufferSubData
-	dir data in
-	len data size
-	var_flag data nullAllowed
-
-#void glClipPlanex(GLenum plane, GLfixed *eqn)
-glClipPlanex
-	dir eqn in
-	len eqn (4 * sizeof(GLfixed))
-
-#void glColorPointer(GLint size, GLenum type, GLsizei stride, GLvoid *pointer)
-#we treat the pointer as offset to a VBO
-glColorPointer
-	len pointer (sizeof(unsigned int))
-	flag unsupported
-
-#void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLvoid *data)
-glCompressedTexImage2D
-	len data imageSize
+    len data size
     var_flag data nullAllowed
 
-#void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, GLvoid *data)
+glBufferSubData
+    dir data in
+    len data size
+    var_flag data nullAllowed
+
+glClipPlanex
+    dir eqn in
+    len eqn (4 * sizeof(GLfixed))
+
+glColorPointer
+    len pointer (sizeof(unsigned int))
+    flag unsupported
+
+glCompressedTexImage2D
+    len data imageSize
+    var_flag data nullAllowed
+
 glCompressedTexSubImage2D
-	len data imageSize
+    len data imageSize
         var_flag data nullAllowed
 
-#void glDeleteBuffers(GLsizei n, GLuint *buffers)
 glDeleteBuffers
-    flag custom_decoder
-	len buffers (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    len buffers (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glDeleteTextures(GLsizei n, GLuint *textures)
 glDeleteTextures
-    flag custom_decoder
-	len textures (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    len textures (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#this function is marked as unsupported - it shouldn't be called directly
-#instead it translated into - glDrawDirectElements and glDrawIndirectElements
-#void glDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid *indices)
 glDrawElements
-	flag unsupported
+    flag unsupported
 
-
-#void glFogxv(GLenum pname, GLfixed *params)
-glFogxv
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glGetBooleanv(GLenum pname, GLboolean *params)
 glGetBooleanv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLboolean))
+    dir params out
 
-#void glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
 glGetBufferParameteriv
-	len params (sizeof(GLint))
-	dir params out
+    len params (sizeof(GLint))
+    dir params out
 
-#void glGenBuffers(GLsizei n, GLuint *buffers)
 glGenBuffers
-    flag custom_decoder
-	len buffers (n * sizeof(GLuint))
-	dir buffers out
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    len buffers (n * sizeof(GLuint))
+    dir buffers out
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenTextures(GLsizei n, GLuint *textures)
 glGenTextures
-    flag custom_decoder
-	len textures (n * sizeof(GLuint))
-	dir textures out
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    len textures (n * sizeof(GLuint))
+    dir textures out
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGetFixedv(GLenum pname, GLfixed *params)
 glGetFixedv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glGetIntegerv(GLenum pname, GLint *params)
 glGetIntegerv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
+    dir params out
 
-#void glGetLightxv(GLenum light, GLenum pname, GLfixed *params)
 glGetLightxv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glGetMaterialxv(GLenum face, GLenum pname, GLfixed *params)
 glGetMaterialxv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glGetPointerv(GLenum pname, void **params)
 glGetPointerv
-	flag unsupported
+    flag unsupported
 
-#GLubyte* glGetString(GLenum name)
 glGetString
-  flag unsupported
+    flag unsupported
 
-#void glGetTexEnviv(GLenum env, GLenum pname, GLint *params)
 glGetTexEnviv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
+    dir params out
 
-#void glGetTexEnvxv(GLenum env, GLenum pname, GLfixed *params)
 glGetTexEnvxv
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params)
 glGetTexParameteriv
-	dir params out
-	len params (sizeof(GLint))
+    dir params out
+    len params (sizeof(GLint))
 
-#void glGetTexParameterxv(GLenum target, GLenum pname, GLfixed *params)
 glGetTexParameterxv
-	dir params out
-	len params (sizeof(GLfixed))
+    dir params out
+    len params (sizeof(GLfixed))
 
-#void glLightModelxv(GLenum pname, GLfixed *params)
-glLightModelxv
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glLightxv(GLenum light, GLenum pname, GLfixed *params)
-glLightxv
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glLoadMatrixx(GLfixed *m)
 glLoadMatrixx
-	len m (16 * sizeof(GLfixed))
+    len m (16 * sizeof(GLfixed))
 
-#void glMaterialxv(GLenum face, GLenum pname, GLfixed *params)
-glMaterialxv
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glMultMatrixx(GLfixed *m)
 glMultMatrixx
-	len m (16 * sizeof(GLfixed))
+    len m (16 * sizeof(GLfixed))
 
-#void glNormalPointer(GLenum type, GLsizei stride, GLvoid *pointer)
-#we treat the pointer as an offset to a VBO
 glNormalPointer
-	len pointer (sizeof(unsigned int))
-	flag unsupported
+    len pointer (sizeof(unsigned int))
+    flag unsupported
 
-#void glPointParameterxv(GLenum pname, GLfixed *params)
-glPointParameterxv
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
 glReadPixels
-	dir pixels out
-	len pixels glesv1_enc::pixelDataSize(self, width, height, format, type, 1)
+    dir pixels out
+    len pixels glesv1_enc::pixelDataSize(self, width, height, format, type, 1)
 
-#void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLvoid *pointer)
 glTexCoordPointer
-	len pointer (sizeof(unsigned int))
-	flag unsupported
+    len pointer (sizeof(unsigned int))
+    flag unsupported
 
-#void glTexEnviv(GLenum target, GLenum pname, GLint *params)
-glTexEnviv
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
-
-#void glTexEnvxv(GLenum target, GLenum pname, GLfixed *params)
-glTexEnvxv
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLvoid *pixels)
 glTexImage2D
-	dir pixels in
-	len pixels glesv1_enc::pixelDataSize(self, width, height, format, type, 0)
-	var_flag pixels nullAllowed isLarge
+    dir pixels in
+    len pixels glesv1_enc::pixelDataSize(self, width, height, format, type, 0)
+    var_flag pixels nullAllowed isLarge
 
-#void glTexParameteriv(GLenum target, GLenum pname, GLint *params)
-glTexParameteriv
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
-
-#void glTexParameterxv(GLenum target, GLenum pname, GLfixed *params)
-glTexParameterxv
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
 glTexSubImage2D
-	len pixels glesv1_enc::pixelDataSize(self, width, height, format, type, 0)
-        var_flag pixels nullAllowed isLarge
+    len pixels glesv1_enc::pixelDataSize(self, width, height, format, type, 0)
+    var_flag pixels nullAllowed isLarge
 
-#void glVertexPointer(GLint size, GLenum type, GLsizei stride, GLvoid *pointer)
-# we treat the pointer as an offset to a VBO
 glVertexPointer
-	flag unsupported
+    flag unsupported
 
-#void glPointSizePointerOES(GLenum type, GLsizei stride, GLvoid *pointer)
 glPointSizePointerOES
-	len pointer (sizeof(unsigned int))
-	flag unsupported
+    len pointer (sizeof(unsigned int))
+    flag unsupported
 
-#void glGetClipPlanef(GLenum pname, GLfloat * eqn)
 glGetClipPlanef
-	dir eqn out
-	len eqn (4 * sizeof(GLfloat))
+    dir eqn out
+    len eqn (4 * sizeof(GLfloat))
 
-#void glVertexPointerData(GLint size, GLenum type, GLsizei stride, void *data, GLuint datalen)
 glVertexPointerData
-	len data datalen
-	custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char *)data, size, type, stride, datalen)
-	flag custom_decoder
-	flag not_api
+    len data datalen
+    flag not_api
 
-#void glColorPointerData(GLint size, GLenum type, GLsizei stride, void *data, GLuint datalen)
 glColorPointerData
-	len data datalen
-	flag custom_decoder
-	custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char *)data, size, type, stride, datalen)
-	flag not_api
+    len data datalen
+    flag not_api
 
-#void glNormalPointerData(GLenum type, GLsizei stride, void *data, GLuint datalen)
 glNormalPointerData
-	len data datalen
-	flag custom_decoder
-	custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char *)data, 3, type, stride, datalen)
-	flag not_api
+    len data datalen
+    flag not_api
 
-#void glPointSizePointerData(GLenum type, GLsizei stride, void *data, GLuint datalen)
 glPointSizePointerData
-	len data datalen
-	flag custom_decoder
-	custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char *)data, 1, type, stride, datalen)
-	flag not_api
+    len data datalen
+    flag not_api
 
-#void glTexCoordPointerData(GLint size, GLenum type, GLsizei stride, void *data, GLuint datalen)
 glTexCoordPointerData
-	len data datalen
-	flag custom_decoder
-	custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char *)data, size, type, stride, datalen)
-	flag not_api
+    len data datalen
+    flag not_api
 
-#void glWeightPointerData(GLint size, GLenum type, GLsizei stride,  void * data, GLuint datalen)
 glWeightPointerData
-  	len data datalen
-  	custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char*)data, size, type, stride, datalen)
-  	flag custom_decoder
-	flag not_api
+    len data datalen
+    flag not_api
 
-#void glMatrixIndexPointerData(GLint size, GLenum type, GLsizei stride,  void * data, GLuint datalen)
 glMatrixIndexPointerData
-	len data datalen
-  	custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char*)data, size, type, stride, datalen)
-  	flag custom_decoder
-	flag not_api
+    len data datalen
+    flag not_api
 
 glVertexPointerOffset
-	flag custom_decoder
-	flag not_api
+    flag not_api
+
 glNormalPointerOffset
-	flag custom_decoder
-	flag not_api
+    flag not_api
+
 glTexCoordPointerOffset
-	flag custom_decoder
-	flag not_api
+    flag not_api
+
 glPointSizePointerOffset
-	flag custom_decoder
-	flag not_api
+    flag not_api
+
 glColorPointerOffset
-	flag custom_decoder
-	flag not_api
+    flag not_api
+
 glWeightPointerOffset
-    flag custom_decoder
-	flag not_api
+    flag not_api
+
 glMatrixIndexPointerOffset
-    flag custom_decoder
-	flag not_api
+    flag not_api
 
 glDrawElementsData
-	len data datalen
-	flag custom_decoder
-	flag not_api
+    len data datalen
+    flag not_api
 
 glDrawElementsOffset
-	flag custom_decoder
-	flag not_api
+    flag not_api
 
 glGetCompressedTextureFormats
-	dir formats out
-	len formats (count * sizeof(GLint))
-	flag custom_decoder
-	flag not_api
+    dir formats out
+    len formats (count * sizeof(GLint))
+    flag not_api
 
 glFinishRoundTrip
-	flag custom_decoder
-	flag not_api
+    flag not_api
 
-#gles1 extensions
-
-#void glDrawTexsvOES(GLshort *coords)
 glDrawTexsvOES
-	len coords (5 * sizeof(GLshort))
+    len coords (5 * sizeof(GLshort))
 
-#void glDrawTexivOES(GLint *coords)
 glDrawTexivOES
-	len coords (5 * sizeof(GLint))
+    len coords (5 * sizeof(GLint))
 
-#void glDrawTexxvOES(GLfixed *coords)
 glDrawTexxvOES
-	len coords (5 * sizeof(GLfixed))
+    len coords (5 * sizeof(GLfixed))
 
-#void glDrawTexfvOES(GLfloat *coords)
 glDrawTexfvOES
-	len coords (5 * sizeof(GLfloat))
+    len coords (5 * sizeof(GLfloat))
 
-#glClipPlanexOES(GLenum plane, const GLfixed * equation)
 glClipPlanexOES
-	dir equation in
-	len equation (4 * sizeof(GLfixed))
+    dir equation in
+    len equation (4 * sizeof(GLfixed))
 
-#glClipPlanexIMG(GLenum plane, const GLfixed * equation)
 glClipPlanexIMG
-	dir equation in
-	len equation (4 * sizeof(GLfixed))
+    dir equation in
+    len equation (4 * sizeof(GLfixed))
 
-#void glFogxvOES(GLenum pname, GLfixed *params)
 glFogxvOES
-	dir params in
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params in
 
-#void glGetClipPlanexOES(GLenum pname,  GLfixed * eqn)
 glGetClipPlanexOES
-	dir eqn out
-	len eqn (4 * sizeof(GLfixed))
+    dir eqn out
+    len eqn (4 * sizeof(GLfixed))
 
-#void glGetClipPlanex(GLenum pname,  GLfixed * eqn)
 glGetClipPlanex
-	dir eqn out
-	len eqn (4 * sizeof(GLfixed))
+    dir eqn out
+    len eqn (4 * sizeof(GLfixed))
 
-#void glGetFixedvOES(GLenum pname, GLfixed *params)
 glGetFixedvOES
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glGetLightxvOES(GLenum light, GLenum pname, GLfixed *params)
 glGetLightxvOES
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glGetMaterialxvOES(GLenum face, GLenum pname, GLfixed *params)
 glGetMaterialxvOES
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glGetTexEnvxvOES(GLenum env, GLenum pname, GLfixed *params)
 glGetTexEnvxvOES
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glGetTexParameterxvOES(GLenum target, GLenum pname, GLfixed *params)
 glGetTexParameterxvOES
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params out
 
-#void glLightModelxvOES(GLenum pname, GLfixed *params)
 glLightModelxvOES
-	dir params in
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params in
 
-#void glLightxvOES(GLenum light, GLenum pname, GLfixed *params)
 glLightxvOES
-	dir params in
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params in
 
-#void glLoadMatrixxOES(GLfixed *m)
 glLoadMatrixxOES
-	dir m in
-	len m (16 * sizeof(GLfixed))
+    dir m in
+    len m (16 * sizeof(GLfixed))
 
-#void glMaterialxvOES(GLenum face, GLenum pname, GLfixed *params)
 glMaterialxvOES
-	dir params in
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params in
 
-#void glMultMatrixxOES(GLfixed *m)
 glMultMatrixxOES
-	dir m in
-	len m (16 * sizeof(GLfixed))
+    dir m in
+    len m (16 * sizeof(GLfixed))
 
-#void glPointParameterxvOES(GLenum pname, GLfixed *params)
 glPointParameterxvOES
-	dir params in
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params in
 
-#void glTexEnvxvOES(GLenum target, GLenum pname, GLfixed *params)
 glTexEnvxvOES
-	dir params in
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params in
 
-#void glTexParameterxvOES(GLenum target, GLenum pname, GLfixed *params)
 glTexParameterxvOES
-	dir params in
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
+    dir params in
 
-#void glDeleteRenderbuffersOES(GLsizei n, GLuint *renderbuffers)
 glDeleteRenderbuffersOES
-    flag custom_decoder
-	dir renderbuffers in
-	len renderbuffers (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    dir renderbuffers in
+    len renderbuffers (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenRenderbuffersOES(GLsizei n, GLuint *renderbuffers)
 glGenRenderbuffersOES
-    flag custom_decoder
-	dir renderbuffers out 
-	len renderbuffers (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    dir renderbuffers out
+    len renderbuffers (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint *params)
 glGetRenderbufferParameterivOES
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
+    dir params out
 
-#void glDeleteFramebuffersOES(GLsizei n, GLuint *framebuffers)
 glDeleteFramebuffersOES
-    flag custom_decoder
-	dir framebuffers in
-	len framebuffers (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    dir framebuffers in
+    len framebuffers (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenFramebuffersOES(GLsizei n, GLuint *framebuffers)
 glGenFramebuffersOES
-    flag custom_decoder
-	dir framebuffers out
-	len framebuffers (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    dir framebuffers out
+    len framebuffers (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint *params)
 glGetFramebufferAttachmentParameterivOES
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
+    dir params out
 
-#void* glMapBufferOES(GLenum target, GLenum access)
 glMapBufferOES
-	flag unsupported
+    flag unsupported
 
-#void glGetBufferPointervOES(GLenum target, GLenum pname, GLvoid ** params)
 glGetBufferPointervOES
-	flag unsupported
+    flag unsupported
 
-#void glMatrixIndexPointerOES(GLint size, GLenum type, GLsizei stride, GLvoid *pointer)
 glMatrixIndexPointerOES
-	len pointer (sizeof(unsigned int))
-	flag unsupported
+    len pointer (sizeof(unsigned int))
+    flag unsupported
 
-#void glWeightPointerOES(GLint size, GLenum type, GLsizei stride, GLvoid *pointer)
 glWeightPointerOES
-	len pointer (sizeof(unsigned int))
-	flag unsupported
+    len pointer (sizeof(unsigned int))
+    flag unsupported
 
-#glQueryMatrixxOES(GLfixed * mantissa, GLint * exponent)
 glQueryMatrixxOES
-	dir mantissa out
-	len mantissa (16 * sizeof(GLfixed))
-	dir exponent out
-	len exponent (16 * sizeof(GLfixed))
+    dir mantissa out
+    len mantissa (16 * sizeof(GLfixed))
+    dir exponent out
+    len exponent (16 * sizeof(GLfixed))
 
-#void glClipPlanefOES(GLenum plane, GLfloat *equation)
 glClipPlanefOES
-	dir equation in
-	len equation (4 * sizeof(GLfloat))
+    dir equation in
+    len equation (4 * sizeof(GLfloat))
 
-#void glClipPlanefIMG(GLenum plane, GLfloat *equation)
 glClipPlanefIMG
-	dir equation in
-	len equation (4 * sizeof(GLfloat))
+    dir equation in
+    len equation (4 * sizeof(GLfloat))
 
-#void glGetClipPlanefOES(GLenum pname, GLfloat * eqn)
 glGetClipPlanefOES
-	dir eqn out
-	len eqn (4 * sizeof(GLfloat))
+    dir eqn out
+    len eqn (4 * sizeof(GLfloat))
 
-#void glTexGenfvOES(GLenum coord, GLenum pname, GLfloat *params)
-glTexGenfvOES
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glTexGenivOES(GLenum coord, GLenum pname, GLint *params)
-glTexGenivOES
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
-
-#void glTexGenxvOES(GLenum coord, GLenum pname, GLfixed *params)
-glTexGenxvOES
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glGetTexGenfvOES(GLenum coord, GLenum pname, GLfloat *params)
-glGetTexGenfvOES
-	len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-#void glGetTexGenivOES(GLenum coord, GLenum pname, GLint *params)
-glGetTexGenivOES
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
-
-#void glGetTexGenxvOES(GLenum coord, GLenum pname, GLfixed *params)
-glGetTexGenxvOES
-	len params (glUtilsParamSize(pname) * sizeof(GLfixed))
-
-#void glDeleteVertexArraysOES(GLsizei n, const GLuint *arrays)
 glDeleteVertexArraysOES
-    flag custom_decoder
-	dir arrays in
-	len arrays (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    dir arrays in
+    len arrays (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenVertexArraysOES(GLsizei n, GLuint *arrays)
 glGenVertexArraysOES
-    flag custom_decoder
-	dir arrays out
-	len arrays (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    dir arrays out
+    len arrays (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments)
 glDiscardFramebufferEXT
-	dir attachments in
-	len attachments (numAttachments * sizeof(const GLenum))
+    dir attachments in
+    len attachments (numAttachments * sizeof(const GLenum))
 
-#void glMultiDrawArraysEXT(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount)
 glMultiDrawArraysEXT
-	flag unsupported
-	
-#void glMultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount)
+    flag unsupported
+
 glMultiDrawElementsEXT
-	flag unsupported
+    flag unsupported
 
-#void glMultiDrawArraysSUN(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount)
 glMultiDrawArraysSUN
-	flag unsupported
-	
-#void glMultiDrawElementsSUN(GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount)
+    flag unsupported
+
 glMultiDrawElementsSUN
-	flag unsupported
+    flag unsupported
 
-#void glDeleteFencesNV(GLsizei n, const GLuint *fences)
 glDeleteFencesNV
-	dir fences in
-	len fences (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    dir fences in
+    len fences (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenFencesNV(GLsizei n, GLuint *fences)
 glGenFencesNV
-	dir fences in
-	len fences (n * sizeof(GLuint))
-    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } 
+    dir fences in
+    len fences (n * sizeof(GLuint))
+    param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
 glGetFenceivNV
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
+    dir params out
 
-#void glGetDriverControlsQCOM(GLint *num, GLsizei size, GLuint *driverControls)
 glGetDriverControlsQCOM
-	dir num out
-	len num (1 * sizeof(GLint))
-	dir driverControls out
-	len driverControls (size * sizeof(GLuint))
+    dir num out
+    len num (1 * sizeof(GLint))
+    dir driverControls out
+    len driverControls (size * sizeof(GLuint))
 
-#void glGetDriverControlStringQCOM(GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString)
 glGetDriverControlStringQCOM
-	dir length out
-	len length (1 * sizeof(GLsizei))
-	dir driverControlString out
-	len driverControlString (1 * sizeof(GLchar))
+    dir length out
+    len length (1 * sizeof(GLsizei))
+    dir driverControlString out
+    len driverControlString (1 * sizeof(GLchar))
 
-#void glExtGetTexturesQCOM(GLuint *textures, GLint maxTextures, GLint *numTextures)
 glExtGetTexturesQCOM
-	dir textures out
-	len textures (maxTextures * sizeof(GLuint))
-	dir numTextures out
-	len numTextures (1 * sizeof(GLint))
+    dir textures out
+    len textures (maxTextures * sizeof(GLuint))
+    dir numTextures out
+    len numTextures (1 * sizeof(GLint))
 
-#void glExtGetBuffersQCOM(GLuint *buffers, GLint maxBuffers, GLint *numBuffers)
 glExtGetBuffersQCOM
-	dir buffers out
-	len buffers (maxBuffers * sizeof(GLuint))
-	dir numBuffers out
-	len numBuffers (1 * sizeof(GLint))
+    dir buffers out
+    len buffers (maxBuffers * sizeof(GLuint))
+    dir numBuffers out
+    len numBuffers (1 * sizeof(GLint))
 
-#void glExtGetRenderbuffersQCOM(GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers)
 glExtGetRenderbuffersQCOM
-	dir renderbuffers out
-	len renderbuffers (maxRenderbuffers * sizeof(GLuint))
-	dir numRenderbuffers out
-	len numRenderbuffers (1 * sizeof(GLint))
+    dir renderbuffers out
+    len renderbuffers (maxRenderbuffers * sizeof(GLuint))
+    dir numRenderbuffers out
+    len numRenderbuffers (1 * sizeof(GLint))
 
-#void glExtGetFramebuffersQCOM(GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers)
 glExtGetFramebuffersQCOM
-	dir framebuffers out
-	len framebuffers (maxFramebuffers * sizeof(GLuint))
-	dir numFramebuffers out
-	len numFramebuffers (1 * sizeof(GLint))
+    dir framebuffers out
+    len framebuffers (maxFramebuffers * sizeof(GLuint))
+    dir numFramebuffers out
+    len numFramebuffers (1 * sizeof(GLint))
 
-#void glExtGetTexLevelParameterivQCOM(GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params)
 glExtGetTexLevelParameterivQCOM
-	dir params out
-	len params (glUtilsParamSize(pname) * sizeof(GLint))
+    dir params out
 
-#void glExtGetTexSubImageQCOM(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels)
 glExtGetTexSubImageQCOM
-	dir texels out
-	len texels (depth * glesv1_enc::pixelDataSize(self, width, height, format, type, 0))
+    dir texels out
+    len texels (depth * glesv1_enc::pixelDataSize(self, width, height, format, type, 0))
 
-#void glExtGetBufferPointervQCOM(GLenum target, GLvoid **params)
 glExtGetBufferPointervQCOM
-	flag unsupported
+    flag unsupported
 
-#void glExtGetShadersQCOM(GLuint *shaders, GLint maxShaders, GLint *numShaders)
 glExtGetShadersQCOM
-	dir shaders out
-	len shaders (maxShaders * sizeof(GLuint))
-	dir numShaders out
-	len numShaders (1 * sizeof(GLint))
+    dir shaders out
+    len shaders (maxShaders * sizeof(GLuint))
+    dir numShaders out
+    len numShaders (1 * sizeof(GLint))
 
-#void glExtGetProgramsQCOM(GLuint *programs, GLint maxPrograms, GLint *numPrograms)
 glExtGetProgramsQCOM
-	dir programs out
-	len programs (maxPrograms * sizeof(GLuint))
-	dir numPrograms out
-	len numPrograms (1 * sizeof(GLint))
+    dir programs out
+    len programs (maxPrograms * sizeof(GLuint))
+    dir numPrograms out
+    len numPrograms (1 * sizeof(GLint))
 
-#void glExtGetProgramBinarySourceQCOM(GLuint program, GLenum shadertype, GLchar *source, GLint *length)
 glExtGetProgramBinarySourceQCOM
-	flag unsupported
+    flag unsupported
diff --git a/host/libs/virglrenderer/GLESv1_dec/gles1_types.h b/host/libs/virglrenderer/GLESv1_dec/gles1_types.h
index c8355ad..097e03f 100644
--- a/host/libs/virglrenderer/GLESv1_dec/gles1_types.h
+++ b/host/libs/virglrenderer/GLESv1_dec/gles1_types.h
@@ -1,21 +1,19 @@
 /*
-* 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.
-*/
-#ifndef __GLES1_TYPES__H
-#define __GLES1_TYPES__H
+ * Copyright (C) 2018 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.
+ */
+#pragma once
 
-#include "gl_base_types.h"
-
-#endif  // __GLES1_TYPES__H
+#include <GLES/gl.h>
+#include <GLES/glext.h>
diff --git a/host/libs/virglrenderer/GLESv3.cpp b/host/libs/virglrenderer/GLESv3.cpp
new file mode 100644
index 0000000..dd2707d
--- /dev/null
+++ b/host/libs/virglrenderer/GLESv3.cpp
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2018 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 <OpenGLESDispatch/GLESv3Dispatch.h>
+
+#include "GLESv3.h"
+
+#include <string>
+#include <vector>
+
+// Stubs (common)
+
+static void glDeleteFencesNV(GLsizei, const GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glDisableDriverControlQCOM(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glDiscardFramebufferEXT(GLenum, GLsizei, const GLenum*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glEnableDriverControlQCOM(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glEndTilingQCOM(GLbitfield) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetBufferPointervQCOM(GLenum, GLvoid**) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetBuffersQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetFramebuffersQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetProgramBinarySourceQCOM(GLuint, GLenum, GLchar*, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetProgramsQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetRenderbuffersQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetShadersQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetTexLevelParameterivQCOM(GLuint, GLenum, GLint, GLenum, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetTexSubImageQCOM(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei,
+                                    GLenum, GLenum, GLvoid*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glExtGetTexturesQCOM(GLuint*, GLint, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLboolean glExtIsProgramBinaryQCOM(GLuint) {
+    printf("%s: not implemented\n", __func__);
+    return GL_FALSE;
+}
+
+static void glExtTexObjectStateOverrideiQCOM(GLenum, GLenum, GLint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glFinishFenceNV(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glFramebufferTexture2DMultisampleIMG(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGenFencesNV(GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetDriverControlsQCOM(GLint*, GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetDriverControlStringQCOM(GLuint, GLsizei, GLsizei*, GLchar*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetFenceivNV(GLuint, GLenum, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLboolean glIsFenceNV(GLuint) {
+    printf("%s: not implemented\n", __func__);
+    return GL_FALSE;
+}
+
+static void* glMapBufferOES(GLenum, GLenum) {
+    printf("%s: not implemented\n", __func__);
+    return nullptr;
+}
+
+static void glMultiDrawArraysEXT(GLenum, const GLint*, const GLsizei*, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glMultiDrawElementsEXT(GLenum, const GLsizei*, GLenum, const GLvoid* const*, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glRenderbufferStorageMultisampleIMG(GLenum, GLsizei, GLenum, GLsizei, GLsizei) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glSetFenceNV(GLuint, GLenum) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glStartTilingQCOM(GLuint, GLuint, GLuint, GLuint, GLbitfield) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static GLboolean glTestFenceNV(GLuint) {
+    printf("%s: not implemented\n", __func__);
+    return GL_FALSE;
+}
+
+// Stubs (ES 3.1)
+
+static void glBeginPerfMonitorAMD(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glCoverageMaskNV(GLboolean) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glCoverageOperationNV(GLenum) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glDeletePerfMonitorsAMD(GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glEndPerfMonitorAMD(GLuint) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGenPerfMonitorsAMD(GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetPerfMonitorCounterDataAMD(GLuint, GLenum, GLsizei, GLuint*, GLint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetPerfMonitorCounterInfoAMD(GLuint, GLuint, GLenum, GLvoid*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetPerfMonitorCountersAMD(GLuint, GLint*, GLint*, GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetPerfMonitorCounterStringAMD(GLuint, GLuint, GLsizei, GLsizei*, GLchar*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetPerfMonitorGroupsAMD(GLint*, GLsizei, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glGetPerfMonitorGroupStringAMD(GLuint, GLsizei, GLsizei*, GLchar*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void glSelectPerfMonitorCountersAMD(GLuint, GLboolean, GLuint, GLint, GLuint*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+// Non-stubs (common)
+
+static void glDrawElementsData(GLenum mode, GLsizei count, GLenum type, void* indices, GLuint) {
+    s_gles3.glDrawElements(mode, count, type, indices);
+}
+
+static void glDrawElementsOffset(GLenum mode, GLsizei count, GLenum type, GLuint offset) {
+    s_gles3.glDrawElements(mode, count, type, reinterpret_cast<const GLvoid*>(offset));
+}
+
+static GLint glFinishRoundTrip() {
+    s_gles3.glFinish();
+    return 0;
+}
+
+static void glGetCompressedTextureFormats(int count, GLint* formats) {
+    int nFormats;
+    s_gles3.glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &nFormats);
+    if (nFormats <= count)
+        s_gles3.glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
+}
+
+// Non-stubs (ES 3.1)
+
+struct GlSync {
+    GlSync(GLESv3* ctx_, GLsync sync_) : sync(sync_), id(ctx_->sync_nextId++), ctx(ctx_) {
+        ctx->sync_map.emplace(id, this);
+    }
+
+    ~GlSync() {
+        ctx->sync_map.erase(id);
+    }
+
+    GLsync sync;
+    uint64_t id;
+
+  private:
+    GLESv3* ctx;
+};
+
+static GLenum glClientWaitSyncAEMU(void* ctx_, uint64_t wait_on, GLbitfield flags,
+                                   GLuint64 timeout) {
+    GLESv3* ctx = static_cast<GLESv3*>(ctx_);
+
+    std::map<uint64_t, GlSync*>::iterator it;
+    it = ctx->sync_map.find(wait_on);
+    if (it == ctx->sync_map.end())
+        return GL_INVALID_VALUE;
+
+    GlSync* sync = it->second;
+    return s_gles3.glClientWaitSync(sync->sync, flags, timeout);
+}
+
+static void glCompressedTexImage2DOffsetAEMU(GLenum target, GLint level, GLenum internalformat,
+                                             GLsizei width, GLsizei height, GLint border,
+                                             GLsizei imageSize, GLuint offset) {
+    s_gles3.glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize,
+                                   reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glCompressedTexImage3DOffsetAEMU(GLenum target, GLint level, GLenum internalformat,
+                                             GLsizei width, GLsizei height, GLsizei depth,
+                                             GLint border, GLsizei imageSize, GLuint offset) {
+    s_gles3.glCompressedTexImage3D(target, level, internalformat, width, height, depth, border,
+                                   imageSize, reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glCompressedTexSubImage2DOffsetAEMU(GLenum target, GLint level, GLint xoffset,
+                                                GLint yoffset, GLsizei width, GLsizei height,
+                                                GLenum format, GLsizei imageSize, GLuint offset) {
+    s_gles3.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+                                      imageSize, reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glCompressedTexSubImage3DOffsetAEMU(GLenum target, GLint level, GLint xoffset,
+                                                GLint yoffset, GLint zoffset, GLsizei width,
+                                                GLsizei height, GLsizei depth, GLenum format,
+                                                GLsizei imageSize, GLuint offset) {
+    s_gles3.glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth,
+                                      format, imageSize, reinterpret_cast<const GLvoid*>(offset));
+}
+
+static GLuint glCreateShaderProgramvAEMU(GLenum type, GLsizei, const char* packedStrings, GLuint) {
+    return s_gles3.glCreateShaderProgramv(type, 1, &packedStrings);
+}
+
+static void glDeleteSyncAEMU(void* ctx_, uint64_t to_delete) {
+    GLESv3* ctx = static_cast<GLESv3*>(ctx_);
+
+    std::map<uint64_t, GlSync*>::iterator it;
+    it = ctx->sync_map.find(to_delete);
+    if (it == ctx->sync_map.end())
+        return;
+
+    GlSync* sync = it->second;
+    s_gles3.glDeleteSync(sync->sync);
+    delete sync;
+}
+
+static void glDrawArraysIndirectDataAEMU(GLenum mode, const void* indirect, GLuint) {
+    s_gles3.glDrawArraysIndirect(mode, indirect);
+}
+
+static void glDrawArraysIndirectOffsetAEMU(GLenum mode, GLuint offset) {
+    s_gles3.glDrawArraysIndirect(mode, reinterpret_cast<const void*>(offset));
+}
+
+static void glDrawElementsIndirectDataAEMU(GLenum mode, GLenum type, const void* indirect, GLuint) {
+    s_gles3.glDrawElementsIndirect(mode, type, indirect);
+}
+
+static void glDrawElementsIndirectOffsetAEMU(GLenum mode, GLenum type, GLuint offset) {
+    s_gles3.glDrawElementsIndirect(mode, type, reinterpret_cast<const void*>(offset));
+}
+
+static void glDrawElementsInstancedDataAEMU(GLenum mode, GLsizei count, GLenum type,
+                                            const void* indices, GLsizei primcount, GLsizei) {
+    s_gles3.glDrawElementsInstanced(mode, count, type, indices, primcount);
+}
+
+static void glDrawElementsInstancedOffsetAEMU(GLenum mode, GLsizei count, GLenum type,
+                                              GLuint offset, GLsizei primcount) {
+    s_gles3.glDrawElementsInstanced(mode, count, type, reinterpret_cast<const void*>(offset),
+                                    primcount);
+}
+
+static void glDrawRangeElementsDataAEMU(GLenum mode, GLuint start, GLuint end, GLsizei count,
+                                        GLenum type, const GLvoid* indices, GLsizei) {
+    s_gles3.glDrawRangeElements(mode, start, end, count, type, indices);
+}
+
+static void glDrawRangeElementsOffsetAEMU(GLenum mode, GLuint start, GLuint end, GLsizei count,
+                                          GLenum type, GLuint offset) {
+    s_gles3.glDrawRangeElements(mode, start, end, count, type,
+                                reinterpret_cast<const GLvoid*>(offset));
+}
+
+static uint64_t glFenceSyncAEMU(void* ctx_, GLenum condition, GLbitfield flags) {
+    GLsync sync_ = s_gles3.glFenceSync(condition, flags);
+    if (sync_ == 0)
+        return 0U;
+
+    GLESv3* ctx = static_cast<GLESv3*>(ctx_);
+    GlSync* sync = new (std::nothrow) GlSync(ctx, sync_);
+    if (!sync) {
+        s_gles3.glDeleteSync(sync_);
+        return 0U;
+    }
+
+    return sync->id;
+}
+
+static void glFlushMappedBufferRangeAEMU(GLenum target, GLintptr offset, GLsizeiptr length,
+                                         GLbitfield access, void* guest_buffer) {
+    if (guest_buffer && length) {
+        void* gpuPtr = s_gles3.glMapBufferRange(target, offset, length, access);
+        if (gpuPtr) {
+            memcpy(gpuPtr, guest_buffer, length);
+            s_gles3.glFlushMappedBufferRange(target, 0, length);
+            s_gles3.glUnmapBuffer(target);
+        }
+    }
+}
+
+static void glGetSyncivAEMU(void* ctx_, uint64_t sync_, GLenum pname, GLsizei bufSize,
+                            GLsizei* length, GLint* values) {
+    GLESv3* ctx = static_cast<GLESv3*>(ctx_);
+
+    std::map<uint64_t, GlSync*>::iterator it;
+    it = ctx->sync_map.find(sync_);
+    if (it == ctx->sync_map.end())
+        return;
+
+    GlSync* sync = it->second;
+    s_gles3.glGetSynciv(sync->sync, pname, bufSize, length, values);
+}
+
+static std::vector<std::string> sUnpackVarNames(GLsizei count, const char* packedNames) {
+    std::vector<std::string> unpacked;
+    GLsizei current = 0;
+
+    while (current < count) {
+        const char* delimPos = strstr(packedNames, ";");
+        size_t nameLen = delimPos - packedNames;
+        std::string next;
+        next.resize(nameLen);
+        memcpy(&next[0], packedNames, nameLen);
+        unpacked.push_back(next);
+        packedNames = delimPos + 1;
+        current++;
+    }
+
+    return unpacked;
+}
+
+static void glGetUniformIndicesAEMU(GLuint program, GLsizei uniformCount, const GLchar* packedNames,
+                                    GLsizei packedLen, GLuint* uniformIndices) {
+    std::vector<std::string> unpacked = sUnpackVarNames(uniformCount, packedNames);
+    GLchar** unpackedArray = new GLchar*[unpacked.size()];
+    GLsizei i = 0;
+    for (auto& elt : unpacked) {
+        unpackedArray[i] = (GLchar*)&elt[0];
+        i++;
+    }
+
+    s_gles3.glGetUniformIndices(program, uniformCount, const_cast<const GLchar**>(unpackedArray),
+                                uniformIndices);
+    delete[] unpackedArray;
+}
+
+static GLboolean glIsSyncAEMU(void* ctx_, uint64_t sync) {
+    GLESv3* ctx = static_cast<GLESv3*>(ctx_);
+    return ctx->sync_map.count(sync) ? GL_TRUE : GL_FALSE;
+}
+
+static void glMapBufferRangeAEMU(GLenum target, GLintptr offset, GLsizeiptr length,
+                                 GLbitfield access, void* mapped) {
+    if ((access & GL_MAP_READ_BIT) ||
+        ((access & GL_MAP_WRITE_BIT) &&
+         (!(access & GL_MAP_INVALIDATE_RANGE_BIT) && !(access & GL_MAP_INVALIDATE_BUFFER_BIT)))) {
+        void* gpuPtr = s_gles3.glMapBufferRange(target, offset, length, access);
+        if (gpuPtr) {
+            if (mapped)
+                memcpy(mapped, gpuPtr, length);
+            s_gles3.glUnmapBuffer(target);
+        }
+    }
+}
+
+static void glReadPixelsOffsetAEMU(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+                                   GLenum type, GLuint offset) {
+    s_gles3.glReadPixels(x, y, width, height, format, type, reinterpret_cast<GLvoid*>(offset));
+}
+
+static void glShaderString(GLuint shader, const GLchar* string, GLsizei) {
+    s_gles3.glShaderSource(shader, 1, &string, NULL);
+}
+
+static void glTexImage2DOffsetAEMU(GLenum target, GLint level, GLint internalformat, GLsizei width,
+                                   GLsizei height, GLint border, GLenum format, GLenum type,
+                                   GLuint offset) {
+    s_gles3.glTexImage2D(target, level, internalformat, width, height, border, format, type,
+                         reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glTexImage3DOffsetAEMU(GLenum target, GLint level, GLint internalFormat, GLsizei width,
+                                   GLsizei height, GLsizei depth, GLint border, GLenum format,
+                                   GLenum type, GLuint offset) {
+    s_gles3.glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type,
+                         reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glTexSubImage2DOffsetAEMU(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                                      GLsizei width, GLsizei height, GLenum format, GLenum type,
+                                      GLuint offset) {
+    s_gles3.glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
+                            reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glTexSubImage3DOffsetAEMU(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                                      GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                      GLenum format, GLenum type, GLuint offset) {
+    s_gles3.glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format,
+                            type, reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glTransformFeedbackVaryingsAEMU(GLuint program, GLsizei count,
+                                            const char* packedVaryings, GLuint packedVaryingsLen,
+                                            GLenum bufferMode) {
+    std::vector<std::string> unpacked = sUnpackVarNames(count, packedVaryings);
+    char** unpackedArray = new char*[unpacked.size()];
+    GLsizei i = 0;
+    for (auto& elt : unpacked) {
+        unpackedArray[i] = &elt[0];
+        i++;
+    }
+
+    s_gles3.glTransformFeedbackVaryings(program, count, const_cast<const char**>(unpackedArray),
+                                        bufferMode);
+    delete[] unpackedArray;
+}
+
+static void glUnmapBufferAEMU(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access,
+                              void* guest_buffer, GLboolean* out_res) {
+    *out_res = GL_TRUE;
+
+    if (access & GL_MAP_WRITE_BIT) {
+        if (guest_buffer) {
+            void* gpuPtr = s_gles3.glMapBufferRange(target, offset, length, access);
+            if (gpuPtr)
+                memcpy(gpuPtr, guest_buffer, length);
+        }
+
+        *out_res = s_gles3.glUnmapBuffer(target);
+    }
+}
+
+static void glVertexAttribIPointerDataAEMU(GLuint index, GLint size, GLenum type, GLsizei,
+                                           void* data, GLuint) {
+    s_gles3.glVertexAttribIPointer(index, size, type, 0, data);
+}
+
+static void glVertexAttribIPointerOffsetAEMU(GLuint index, GLint size, GLenum type, GLsizei,
+                                             GLuint offset) {
+    s_gles3.glVertexAttribIPointer(index, size, type, 0, reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type, GLboolean normalized,
+                                      GLsizei, void* data, GLuint) {
+    s_gles3.glVertexAttribPointer(indx, size, type, normalized, 0, data);
+}
+
+static void glVertexAttribPointerOffset(GLuint indx, GLint size, GLenum type, GLboolean normalized,
+                                        GLsizei, GLuint offset) {
+    s_gles3.glVertexAttribPointer(indx, size, type, normalized, 0,
+                                  reinterpret_cast<const GLvoid*>(offset));
+}
+
+static void glWaitSyncAEMU(void* ctx_, uint64_t wait_on, GLbitfield flags, GLuint64 timeout) {
+    GLESv3* ctx = static_cast<GLESv3*>(ctx_);
+
+    std::map<uint64_t, GlSync*>::iterator it;
+    it = ctx->sync_map.find(wait_on);
+    if (it == ctx->sync_map.end())
+        return;
+
+    GlSync* sync = it->second;
+    s_gles3.glWaitSync(sync->sync, flags, timeout);
+}
+
+#define KNIT(return_type, function_name, signature, callargs) function_name = s_gles3.function_name;
+
+GLESv3::GLESv3() {
+    LIST_GLES3_FUNCTIONS(KNIT, KNIT)
+
+    // Remap some ES 2.0 extensions that become core in ES 3.1
+    glBindVertexArrayOES = glBindVertexArray;
+    glDeleteVertexArraysOES = glDeleteVertexArrays;
+    glGenVertexArraysOES = glGenVertexArrays;
+    glGetProgramBinaryOES = glGetProgramBinary;
+    glIsVertexArrayOES = glIsVertexArray;
+    glProgramBinaryOES = glProgramBinary;
+    glUnmapBufferOES = glUnmapBuffer;
+
+    // Entrypoints requiring custom wrappers (common)
+    glDrawElementsData = ::glDrawElementsData;
+    glDrawElementsOffset = ::glDrawElementsOffset;
+    glFinishRoundTrip = ::glFinishRoundTrip;
+    glGetCompressedTextureFormats = ::glGetCompressedTextureFormats;
+
+    // Entrypoints requiring custom wrappers (ES 3.1)
+    glClientWaitSyncAEMU = ::glClientWaitSyncAEMU;
+    glCompressedTexImage2DOffsetAEMU = ::glCompressedTexImage2DOffsetAEMU;
+    glCompressedTexImage3DOffsetAEMU = ::glCompressedTexImage3DOffsetAEMU;
+    glCompressedTexSubImage2DOffsetAEMU = ::glCompressedTexSubImage2DOffsetAEMU;
+    glCompressedTexSubImage3DOffsetAEMU = ::glCompressedTexSubImage3DOffsetAEMU;
+    glCreateShaderProgramvAEMU = ::glCreateShaderProgramvAEMU;
+    glDeleteSyncAEMU = ::glDeleteSyncAEMU;
+    glDrawArraysIndirectDataAEMU = ::glDrawArraysIndirectDataAEMU;
+    glDrawArraysIndirectOffsetAEMU = ::glDrawArraysIndirectOffsetAEMU;
+    glDrawElementsIndirectDataAEMU = ::glDrawElementsIndirectDataAEMU;
+    glDrawElementsIndirectOffsetAEMU = ::glDrawElementsIndirectOffsetAEMU;
+    glDrawElementsInstancedDataAEMU = ::glDrawElementsInstancedDataAEMU;
+    glDrawElementsInstancedOffsetAEMU = ::glDrawElementsInstancedOffsetAEMU;
+    glDrawRangeElementsDataAEMU = ::glDrawRangeElementsDataAEMU;
+    glDrawRangeElementsOffsetAEMU = ::glDrawRangeElementsOffsetAEMU;
+    glFenceSyncAEMU = ::glFenceSyncAEMU;
+    glFlushMappedBufferRangeAEMU = ::glFlushMappedBufferRangeAEMU;
+    glGetSyncivAEMU = ::glGetSyncivAEMU;
+    glGetUniformIndicesAEMU = ::glGetUniformIndicesAEMU;
+    glIsSyncAEMU = ::glIsSyncAEMU;
+    glMapBufferRangeAEMU = ::glMapBufferRangeAEMU;
+    glReadPixelsOffsetAEMU = ::glReadPixelsOffsetAEMU;
+    glShaderString = ::glShaderString;
+    glTexImage2DOffsetAEMU = ::glTexImage2DOffsetAEMU;
+    glTexImage3DOffsetAEMU = ::glTexImage3DOffsetAEMU;
+    glTexSubImage2DOffsetAEMU = ::glTexSubImage2DOffsetAEMU;
+    glTexSubImage3DOffsetAEMU = ::glTexSubImage3DOffsetAEMU;
+    glTransformFeedbackVaryingsAEMU = ::glTransformFeedbackVaryingsAEMU;
+    glUnmapBufferAEMU = ::glUnmapBufferAEMU;
+    glVertexAttribIPointerDataAEMU = ::glVertexAttribIPointerDataAEMU;
+    glVertexAttribIPointerOffsetAEMU = ::glVertexAttribIPointerOffsetAEMU;
+    glVertexAttribPointerData = ::glVertexAttribPointerData;
+    glVertexAttribPointerOffset = ::glVertexAttribPointerOffset;
+    glWaitSyncAEMU = ::glWaitSyncAEMU;
+
+    // Stub some extensions we will never implement (common)
+    glDeleteFencesNV = ::glDeleteFencesNV;
+    glDisableDriverControlQCOM = ::glDisableDriverControlQCOM;
+    glDiscardFramebufferEXT = ::glDiscardFramebufferEXT;
+    glEnableDriverControlQCOM = ::glEnableDriverControlQCOM;
+    glEndTilingQCOM = ::glEndTilingQCOM;
+    glExtGetBufferPointervQCOM = ::glExtGetBufferPointervQCOM;
+    glExtGetBuffersQCOM = ::glExtGetBuffersQCOM;
+    glExtGetFramebuffersQCOM = ::glExtGetFramebuffersQCOM;
+    glExtGetProgramBinarySourceQCOM = ::glExtGetProgramBinarySourceQCOM;
+    glExtGetProgramsQCOM = ::glExtGetProgramsQCOM;
+    glExtGetRenderbuffersQCOM = ::glExtGetRenderbuffersQCOM;
+    glExtGetShadersQCOM = ::glExtGetShadersQCOM;
+    glExtGetTexLevelParameterivQCOM = ::glExtGetTexLevelParameterivQCOM;
+    glExtGetTexSubImageQCOM = ::glExtGetTexSubImageQCOM;
+    glExtGetTexturesQCOM = ::glExtGetTexturesQCOM;
+    glExtIsProgramBinaryQCOM = ::glExtIsProgramBinaryQCOM;
+    glExtTexObjectStateOverrideiQCOM = ::glExtTexObjectStateOverrideiQCOM;
+    glFinishFenceNV = ::glFinishFenceNV;
+    glFramebufferTexture2DMultisampleIMG = ::glFramebufferTexture2DMultisampleIMG;
+    glGenFencesNV = ::glGenFencesNV;
+    glGetDriverControlsQCOM = ::glGetDriverControlsQCOM;
+    glGetDriverControlStringQCOM = ::glGetDriverControlStringQCOM;
+    glGetFenceivNV = ::glGetFenceivNV;
+    glIsFenceNV = ::glIsFenceNV;
+    glMapBufferOES = ::glMapBufferOES;
+    glMultiDrawArraysEXT = ::glMultiDrawArraysEXT;
+    glMultiDrawElementsEXT = ::glMultiDrawElementsEXT;
+    glRenderbufferStorageMultisampleIMG = ::glRenderbufferStorageMultisampleIMG;
+    glSetFenceNV = ::glSetFenceNV;
+    glStartTilingQCOM = ::glStartTilingQCOM;
+    glTestFenceNV = ::glTestFenceNV;
+
+    // Stub some extensions we will never implement (ES 3.1)
+    glBeginPerfMonitorAMD = ::glBeginPerfMonitorAMD;
+    glCoverageMaskNV = ::glCoverageMaskNV;
+    glCoverageOperationNV = ::glCoverageOperationNV;
+    glDeletePerfMonitorsAMD = ::glDeletePerfMonitorsAMD;
+    glEndPerfMonitorAMD = ::glEndPerfMonitorAMD;
+    glGenPerfMonitorsAMD = ::glGenPerfMonitorsAMD;
+    glGetPerfMonitorCounterDataAMD = ::glGetPerfMonitorCounterDataAMD;
+    glGetPerfMonitorCounterInfoAMD = ::glGetPerfMonitorCounterInfoAMD;
+    glGetPerfMonitorCountersAMD = ::glGetPerfMonitorCountersAMD;
+    glGetPerfMonitorCounterStringAMD = ::glGetPerfMonitorCounterStringAMD;
+    glGetPerfMonitorGroupsAMD = ::glGetPerfMonitorGroupsAMD;
+    glGetPerfMonitorGroupStringAMD = ::glGetPerfMonitorGroupStringAMD;
+    glSelectPerfMonitorCountersAMD = ::glSelectPerfMonitorCountersAMD;
+}
diff --git a/host/libs/virglrenderer/GLESv3.h b/host/libs/virglrenderer/GLESv3.h
new file mode 100644
index 0000000..33eab48
--- /dev/null
+++ b/host/libs/virglrenderer/GLESv3.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include "GLESv3_dec/gles3_dec.h"
+
+#include <map>
+
+struct GlSync;
+
+struct GLESv3 : public gles3_decoder_context_t {
+    GLESv3();
+
+    glDrawBuffers_server_proc_t glDrawBuffersEXT;
+
+    glDrawArraysInstanced_server_proc_t glDrawArraysInstancedEXT;
+    glDrawElementsInstanced_server_proc_t glDrawElementsInstancedEXT;
+
+    glVertexAttribDivisor_server_proc_t glVertexAttribDivisorEXT;
+
+    std::map<uint64_t, GlSync*> sync_map;
+
+  private:
+    uint64_t sync_nextId = 1U;
+    friend struct GlSync;
+};
diff --git a/host/libs/virglrenderer/GLESv3_dec/gles3.attrib b/host/libs/virglrenderer/GLESv3_dec/gles3.attrib
index 6b452f4..d5d8d18 100644
--- a/host/libs/virglrenderer/GLESv3_dec/gles3.attrib
+++ b/host/libs/virglrenderer/GLESv3_dec/gles3.attrib
@@ -1,120 +1,68 @@
 GLOBAL
     base_opcode 2048
-    encoder_headers <string.h> "glUtils.h" "GL2EncoderUtils.h"
 
-#void glBindAttribLocation(GLuint program, GLuint index, GLchar *name)
 glBindAttribLocation
-    flag custom_decoder
     len name (strlen(name) + 1)
 
-#void glBufferData(GLenum target, GLsizeiptr size, GLvoid *data, GLenum usage)
 glBufferData
     len data size
     var_flag data nullAllowed isLarge
 
-#void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data)
 glBufferSubData
     len data size
     var_flag data nullAllowed isLarge
 
-#void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLvoid *data)
 glCompressedTexImage2D
     len data imageSize
     param_check imageSize if(imageSize<0){ ctx->setError(GL_INVALID_VALUE); return; }
     var_flag data nullAllowed isLarge
     param_check imageSize if(imageSize<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, GLvoid *data)
 glCompressedTexSubImage2D
     len data imageSize
     param_check imageSize if(imageSize<0){ ctx->setError(GL_INVALID_VALUE); return; }
     var_flag data nullAllowed isLarge
     param_check imageSize if(imageSize<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-glDeleteShader
-    flag custom_decoder
-
-glDeleteProgram
-    flag custom_decoder
-
-#void glDeleteBuffers(GLsizei n, GLuint *buffers)
 glDeleteBuffers
-    flag custom_decoder
     len buffers (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glDeleteFramebuffers(GLsizei n, GLuint *framebuffers)
 glDeleteFramebuffers
-    flag custom_decoder
     len framebuffers (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers)
 glDeleteRenderbuffers
-    flag custom_decoder
     len renderbuffers (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glDeleteTextures(GLsizei n, GLuint *textures)
 glDeleteTextures
-    flag custom_decoder
     len textures (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid *indices)
 glDrawElements
     flag unsupported
 
-glCreateShader
-    flag custom_decoder
-
-glCompileShader
-    flag custom_decoder
-
-glAttachShader
-    flag custom_decoder
-
-glDetachShader
-    flag custom_decoder
-
-glIsShader
-    flag custom_decoder
-
-glLinkProgram
-    flag custom_decoder
-
-glCreateProgram
-    flag custom_decoder
-
-#void glGenBuffers(GLsizei n, GLuint *buffers)
 glGenBuffers
-    flag custom_decoder
     len buffers (n * sizeof(GLuint))
     dir buffers out
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenFramebuffers(GLsizei n, GLuint *framebuffers)
 glGenFramebuffers
-    flag custom_decoder
     len framebuffers (n * sizeof(GLuint))
     dir framebuffers out
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenRenderbuffers(GLsizei n, GLuint *renderbuffers)
 glGenRenderbuffers
-    flag custom_decoder
     len renderbuffers (n * sizeof(GLuint))
     dir renderbuffers out
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenTextures(GLsizei n, GLuint *textures)
 glGenTextures
-    flag custom_decoder
     len textures (n * sizeof(GLuint))
     dir textures out
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
 glGetActiveAttrib
     param_check bufsize if(bufsize<0){ ctx->setError(GL_INVALID_VALUE); return; }
     len name bufsize
@@ -130,12 +78,11 @@
     len type (sizeof(GLenum))
     var_flag type nullAllowed
 
-#void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
 glGetActiveUniform
     param_check bufsize if(bufsize<0){ ctx->setError(GL_INVALID_VALUE); return; }
     len name bufsize
     dir name out
-      var_flag name nullAllowed
+    var_flag name nullAllowed
     dir length out
     len length (sizeof(GLsizei))
     var_flag length nullAllowed
@@ -146,8 +93,6 @@
     len type (sizeof(GLenum))
     var_flag type nullAllowed
 
-
-#void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders)
 glGetAttachedShaders
     len shaders (maxcount*sizeof(GLuint))
     dir shaders out
@@ -155,44 +100,30 @@
     var_flag count nullAllowed
     len count (sizeof(GLsizei))
 
-#int glGetAttribLocation(GLuint program, GLchar *name)
 glGetAttribLocation
     len name (strlen(name) + 1)
 
-#void glGetBooleanv(GLenum pname, GLboolean *params)
 glGetBooleanv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLboolean))
 
-#void glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
 glGetBufferParameteriv
     len params (sizeof(GLint))
     dir params out
 
-#void glGetFloatv(GLenum pname, GLfloat *params)
 glGetFloatv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLfloat))
 
-#void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params)
 glGetFramebufferAttachmentParameteriv
     dir params out
     len params (sizeof(GLint))
 
-#void glGetIntegerv(GLenum pname, GLint *params)
 glGetIntegerv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
-#void glGetProgramiv(GLuint program, GLenum pname, GLint *params)
 glGetProgramiv
-    flag custom_decoder
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
-#void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog)
 glGetProgramInfoLog
-    flag custom_decoder
     dir infolog out
     len infolog bufsize
     param_check bufsize if(bufsize<0){ ctx->setError(GL_INVALID_VALUE); return; }
@@ -200,22 +131,15 @@
     len length sizeof(GLsizei)
     var_flag length nullAllowed
 
-#void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
 glGetRenderbufferParameteriv
     dir params out
     len params sizeof(GLint)
-# XXX - might change if pname with value larger then one is added
 
-#void glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
 glGetShaderiv
-    flag custom_decoder
     dir params out
     len params sizeof(GLint)
-# XXX - might change if pname with value larger then one is added
 
-#void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog)
 glGetShaderInfoLog
-    flag custom_decoder
     dir length out
     len length (sizeof(GLsizei))
     var_flag length nullAllowed
@@ -223,16 +147,13 @@
     len infolog bufsize
     param_check bufsize if(bufsize<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision)
 glGetShaderPrecisionFormat
     dir range out
     len range (2 * sizeof(GLint))
     dir precision out
     len precision (sizeof(GLint))
 
-#void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
 glGetShaderSource
-    flag custom_decoder
     dir length out
     len length (sizeof(GLsizei))
     var_flag length nullAllowed
@@ -240,428 +161,310 @@
     len source bufsize
     param_check bufsize if(bufsize<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#GLubyte* glGetString(GLenum name)
 glGetString
     flag unsupported
 
-#void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
 glGetTexParameterfv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLfloat))
 
-#void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params)
 glGetTexParameteriv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
-#void glGetUniformfv(GLuint program, GLint location, GLfloat *params)
 glGetUniformfv
     dir params out
     len params glSizeof(glesv2_enc::uniformType(self, program, location))
 
-#void glGetUniformiv(GLuint program, GLint location, GLint *params)
 glGetUniformiv
     dir params out
     len params glSizeof(glesv2_enc::uniformType(self, program, location))
 
-#int glGetUniformLocation(GLuint program, GLchar *name)
 glGetUniformLocation
     len name (strlen(name) + 1)
 
-# client-state shall be handled locally by the encoder in most cases.
-# however, GL_CURRENT_VERTEX_ATTRIB and potential others are handled by the server side,
-# thus we still need to implement it.
-#void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
 glGetVertexAttribfv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLfloat))
 
-#see glGetVertexAttribfv for comments
-#void glGetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
 glGetVertexAttribiv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
-#void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
 glReadPixels
     dir pixels out
     len pixels glesv2_enc::pixelDataSize(self, width, height, format, type, 1)
 
 glReadPixelsOffsetAEMU
-    flag custom_decoder
     flag not_api
 
-#void glShaderBinary(GLsizei n, GLuint *shaders, GLenum binaryformat, GLvoid *binary, GLsizei length)
 glShaderBinary
     flag unsupported
 
-#void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLvoid *pixels)
 glTexImage2D
     dir pixels in
     len pixels glesv2_enc::pixelDataSize(self, width, height, format, type, 0)
     var_flag pixels nullAllowed isLarge
 
-#void glTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
-glTexParameterfv
-    len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-#void glTexParameteriv(GLenum target, GLenum pname, GLint *params)
-glTexParameteriv
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
-
-#void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
 glTexSubImage2D
     len pixels glesv2_enc::pixelDataSize(self, width, height, format, type, 0)
     var_flag pixels nullAllowed isLarge
 
-#void glUniform1fv(GLint location, GLsizei count, GLfloat *v)
 glUniform1fv
     len v (count * sizeof(GLfloat))
 
-#void glUniform1iv(GLint location, GLsizei count, GLint *v)
 glUniform1iv
     len v (count * sizeof(GLint))
 
-#void glUniform2fv(GLint location, GLsizei count, GLfloat *v)
 glUniform2fv
     len v (count * 2 * sizeof(GLfloat))
 
-#void glUniform2iv(GLint location, GLsizei count, GLint *v)
 glUniform2iv
     len v (count * 2 * sizeof(GLint))
 
-#void glUniform3fv(GLint location, GLsizei count, GLfloat *v)
 glUniform3fv
     len v (count * 3 * sizeof(GLfloat))
 
-#void glUniform3iv(GLint location, GLsizei count, GLint *v)
 glUniform3iv
     len v (3 * count * sizeof(GLint))
 
-#void glUniform4fv(GLint location, GLsizei count, GLfloat *v)
 glUniform4fv
     len v (4 * count * sizeof(GLfloat))
 
-#void glUniform4iv(GLint location, GLsizei count, GLint *v)
 glUniform4iv
     len v (4 * count * sizeof(GLint))
 
-#void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value)
 glUniformMatrix2fv
     len value (count * 4 * sizeof(GLfloat))
 
-#void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value)
 glUniformMatrix3fv
     len value (count * 9 * sizeof(GLfloat))
 
-#void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, GLfloat *value)
 glUniformMatrix4fv
     len value (count * 16 * sizeof(GLfloat))
 
-#void glVertexAttrib1fv(GLuint indx, GLfloat *values)
 glVertexAttrib1fv
     len values (sizeof(GLfloat))
-#void glVertexAttrib2fv(GLuint indx, GLfloat *values)
 glVertexAttrib2fv
     len values (2 * sizeof(GLfloat))
 
-#void glVertexAttrib3fv(GLuint indx, GLfloat *values)
 glVertexAttrib3fv
     len values (3 * sizeof(GLfloat))
 
-#void glVertexAttrib4fv(GLuint indx, GLfloat *values)
 glVertexAttrib4fv
     len values (4 * sizeof(GLfloat))
 
-#void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLvoid *ptr)
 glVertexAttribPointer
     flag unsupported
 
-#void glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary)
 glGetProgramBinaryOES
     flag unsupported
 
-#void glProgramBinaryOES(GLuint program, GLenum binaryFormat, GLvoid *binary, GLint length)
 glProgramBinaryOES
     flag unsupported
 
-#void* glMapBufferOES(GLenum target, GLenum access)
 glMapBufferOES
     flag unsupported
 
-#void glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLvoid *pixels)
 glTexImage3DOES
     len pixels glesv2_enc::pixelDataSize3D(self, width, height, depth, format, type, 0)
     var_flag pixels nullAllowed isLarge
 
-#void glTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *pixels)
 glTexSubImage3DOES
     len pixels glesv2_enc::pixelDataSize3D(self, width, height, depth, format, type, 0)
     var_flag pixels nullAllowed isLarge
 
-#void glCompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLvoid *data)
 glCompressedTexImage3DOES
     len data imageSize
     param_check imageSize if(imageSize<0){ ctx->setError(GL_INVALID_VALUE); return; }
     var_flag data nullAllowed isLarge
 
-#void glCompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, GLvoid *data)
 glCompressedTexSubImage3DOES
     len data imageSize
     param_check imageSize if(imageSize<0){ ctx->setError(GL_INVALID_VALUE); return; }
     var_flag data nullAllowed isLarge
 
-#void glDeleteVertexArraysOES(GLsizei n, GLuint *arrays)
 glDeleteVertexArraysOES
-    flag custom_decoder
     len arrays (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-#void glGenVertexArraysOES(GLsizei n, GLuint *arrays)
 glGenVertexArraysOES
-    flag custom_decoder
     len arrays (n * sizeof(GLuint))
     dir arrays out
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-
-#void glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, GLenum *attachments)
 glDiscardFramebufferEXT
     len attachments (numAttachments * sizeof(GLenum))
 
-#void glMultiDrawArraysEXT(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount)
 glMultiDrawArraysEXT
     flag unsupported
-#void glMultiDrawElementsEXT(GLenum mode, GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount)
+
 glMultiDrawElementsEXT
     flag unsupported
 
-
-# handled by encoder
-#void glShaderSource(GLuint shader, GLsizei count, GLstr *string, const GLint *length)
 glShaderSource
     flag unsupported
 
-
-#void glGetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize, GLuint *groups)
 glGetPerfMonitorGroupsAMD
     flag unsupported
 
-#void glGetPerfMonitorCountersAMD(GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
 glGetPerfMonitorCountersAMD
     flag unsupported
 
-#void glGetPerfMonitorGroupStringAMD(GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString)
 glGetPerfMonitorGroupStringAMD
     flag unsupported
 
-#void glGetPerfMonitorCounterStringAMD(GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString)
 glGetPerfMonitorCounterStringAMD
     flag unsupported
 
-#void glGetPerfMonitorCounterInfoAMD(GLuint group, GLuint counter, GLenum pname, GLvoid *data)
 glGetPerfMonitorCounterInfoAMD
     flag unsupported
 
-#void glGenPerfMonitorsAMD(GLsizei n, GLuint *monitors)
 glGenPerfMonitorsAMD
     flag unsupported
 
-#void glDeletePerfMonitorsAMD(GLsizei n, GLuint *monitors)
 glDeletePerfMonitorsAMD
     flag unsupported
 
-#void glSelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
 glSelectPerfMonitorCountersAMD
     flag unsupported
 
-#void glBeginPerfMonitorAMD(GLuint monitor)
 glBeginPerfMonitorAMD
     flag unsupported
 
-#void glEndPerfMonitorAMD(GLuint monitor)
 glEndPerfMonitorAMD
     flag unsupported
 
-#void glGetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
 glGetPerfMonitorCounterDataAMD
     flag unsupported
 
-#void glRenderbufferStorageMultisampleIMG(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
 glRenderbufferStorageMultisampleIMG
     flag unsupported
 
-#void glFramebufferTexture2DMultisampleIMG(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
 glFramebufferTexture2DMultisampleIMG
     flag unsupported
 
-#void glDeleteFencesNV(GLsizei n, GLuint *fences)
 glDeleteFencesNV
     flag unsupported
 
-#void glGenFencesNV(GLsizei n, GLuint *fences)
 glGenFencesNV
     flag unsupported
 
-#GLboolean glIsFenceNV(GLuint fence)
 glIsFenceNV
     flag unsupported
 
-#GLboolean glTestFenceNV(GLuint fence)
 glTestFenceNV
     flag unsupported
 
-#void glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
 glGetFenceivNV
     flag unsupported
 
-#void glFinishFenceNV(GLuint fence)
 glFinishFenceNV
     flag unsupported
 
-#void glSetFenceNV(GLuint fence, GLenum condition)
 glSetFenceNV
     flag unsupported
 
-#void glCoverageMaskNV(GLboolean mask)
 glCoverageMaskNV
     flag unsupported
 
-#void glCoverageOperationNV(GLenum operation)
 glCoverageOperationNV
     flag unsupported
 
-#void glGetDriverControlsQCOM(GLint *num, GLsizei size, GLuint *driverControls)
 glGetDriverControlsQCOM
     flag unsupported
 
-#void glGetDriverControlStringQCOM(GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString)
 glGetDriverControlStringQCOM
     flag unsupported
 
-#void glEnableDriverControlQCOM(GLuint driverControl)
 glEnableDriverControlQCOM
     flag unsupported
 
-#void glDisableDriverControlQCOM(GLuint driverControl)
 glDisableDriverControlQCOM
     flag unsupported
 
-#void glExtGetTexturesQCOM(GLuint *textures, GLint maxTextures, GLint *numTextures)
 glExtGetTexturesQCOM
     flag unsupported
 
-#void glExtGetBuffersQCOM(GLuint *buffers, GLint maxBuffers, GLint *numBuffers)
 glExtGetBuffersQCOM
     flag unsupported
 
-#void glExtGetRenderbuffersQCOM(GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers)
 glExtGetRenderbuffersQCOM
     flag unsupported
 
-#void glExtGetFramebuffersQCOM(GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers)
 glExtGetFramebuffersQCOM
     flag unsupported
 
-#void glExtGetTexLevelParameterivQCOM(GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params)
 glExtGetTexLevelParameterivQCOM
     flag unsupported
 
-#void glExtTexObjectStateOverrideiQCOM(GLenum target, GLenum pname, GLint param)
 glExtTexObjectStateOverrideiQCOM
     flag unsupported
 
-#void glExtGetTexSubImageQCOM(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels)
 glExtGetTexSubImageQCOM
     flag unsupported
 
-#void glExtGetBufferPointervQCOM(GLenum target, GLvoidptr *params)
 glExtGetBufferPointervQCOM
     flag unsupported
 
-#void glExtGetShadersQCOM(GLuint *shaders, GLint maxShaders, GLint *numShaders)
 glExtGetShadersQCOM
     flag unsupported
 
-#void glExtGetProgramsQCOM(GLuint *programs, GLint maxPrograms, GLint *numPrograms)
 glExtGetProgramsQCOM
     flag unsupported
 
-#GLboolean glExtIsProgramBinaryQCOM(GLuint program)
 glExtIsProgramBinaryQCOM
     flag unsupported
 
-#void glExtGetProgramBinarySourceQCOM(GLuint program, GLenum shadertype, GLchar *source, GLint *length)
 glExtGetProgramBinarySourceQCOM
     flag unsupported
 
-#void glStartTilingQCOM(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask)
 glStartTilingQCOM
     flag unsupported
 
-#void glEndTilingQCOM(GLbitfield preserveMask)
 glEndTilingQCOM
     flag unsupported
 
-
-#void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride,  void * data, GLuint datalen)
 glVertexAttribPointerData
     len data datalen
-    custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char *)data, size, type, stride, datalen)
-    flag custom_decoder
     flag not_api
 
 glVertexAttribPointerOffset
-    flag custom_decoder
     flag not_api
 
-#client-state, handled by the encoder
-#GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, GLvoid** pointer)
 glGetVertexAttribPointerv
     flag unsupported
 
 glDrawElementsData
     len data datalen
-    flag custom_decoder
     flag not_api
 
 glDrawElementsOffset
-    flag custom_decoder
     flag not_api
 
-#GL_ENTRY(void, glGetCompressedTextureFormats, int count, GLint *formats)
 glGetCompressedTextureFormats
     dir formats out
     len formats (count * sizeof(GLint))
-    flag custom_decoder
     flag not_api
 
-#GL_ENTRY(void, glShaderString, GLuint shader, GLchar *string, GLsizei len)
 glShaderString
     len string len
-    flag custom_decoder
     flag not_api
 
 glFinishRoundTrip
-    flag custom_decoder
     flag not_api
 
-# GLES 3.0
-
 glGenVertexArrays
-    flag custom_decoder
     len arrays (n * sizeof(GLuint))
     dir arrays out
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
 glDeleteVertexArrays
-    flag custom_decoder
     len arrays (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
 glMapBufferRange
     flag unsupported
+
 glUnmapBuffer
     flag unsupported
+
 glFlushMappedBufferRange
     flag unsupported
 
@@ -669,7 +472,6 @@
     dir mapped out
     len mapped length
     var_flag mapped nullAllowed
-    flag custom_decoder
     flag not_api
 
 glUnmapBufferAEMU
@@ -678,34 +480,27 @@
     var_flag guest_buffer nullAllowed
     dir out_res out
     len out_res (sizeof(GLboolean))
-    flag custom_decoder
     flag not_api
 
 glFlushMappedBufferRangeAEMU
     dir guest_buffer in
     len guest_buffer length
     var_flag guest_buffer nullAllowed
-    flag custom_decoder
     flag not_api
 
 glReadPixelsOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glCompressedTexImage2DOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glCompressedTexSubImage2DOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glTexImage2DOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glTexSubImage2DOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glCopyBufferSubData
@@ -740,7 +535,6 @@
     len packedUniformNames packedLen
     dir uniformIndices out
     len uniformIndices (uniformCount * sizeof(GLuint))
-    flag custom_decoder
     flag not_api
 
 glGetActiveUniformBlockiv
@@ -805,33 +599,26 @@
     flag unsupported
 
 glVertexAttribIPointerOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glVertexAttribIPointerDataAEMU
     len data datalen
-    custom_pack data glUtilsPackPointerData((unsigned char *)ptr, (unsigned char *)data, size, type, stride, datalen)
-    flag custom_decoder
     flag not_api
 
 glGetVertexAttribIiv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
 glGetVertexAttribIuiv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLuint))
 
 glDrawElementsInstanced
     flag unsupported
 
 glDrawElementsInstancedDataAEMU
     len indices datalen
-    flag custom_decoder
     flag not_api
 
 glDrawElementsInstancedOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glDrawRangeElements
@@ -839,11 +626,9 @@
 
 glDrawRangeElementsDataAEMU
     len indices datalen
-    flag custom_decoder
     flag not_api
 
 glDrawRangeElementsOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glFenceSync
@@ -908,13 +693,11 @@
     len attachments (numAttachments * sizeof(GLenum))
 
 glGenTransformFeedbacks
-    flag custom_decoder
     dir ids out
     len ids (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
 glDeleteTransformFeedbacks
-    flag custom_decoder
     len ids (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
@@ -924,7 +707,6 @@
 glTransformFeedbackVaryingsAEMU
     dir packedVaryings in
     len packedVaryings packedVaryingsLen
-    flag custom_decoder
     flag not_api
 
 glGetTransformFeedbackVarying
@@ -943,48 +725,34 @@
     var_flag type nullAllowed
 
 glGenSamplers
-    flag custom_decoder
     dir samplers out
     len samplers (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
 glDeleteSamplers
-    flag custom_decoder
     len samplers (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
-glSamplerParameterfv
-    len params (glUtilsParamSize(pname) * sizeof(GLfloat))
-
-glSamplerParameteriv
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
-
 glGetSamplerParameterfv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLfloat))
 
 glGetSamplerParameteriv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
 glGenQueries
-    flag custom_decoder
     dir queries out
     len queries (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
 glDeleteQueries
-    flag custom_decoder
     len queries (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
 glGetQueryiv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
 glGetQueryObjectuiv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLuint))
 
 glProgramBinary
     len binary length
@@ -1004,11 +772,7 @@
 
 glGetInteger64v
     dir data out
-    len data (glUtilsParamSize(pname) * sizeof(GLint64))
 
-# No need to account for custom sizes since indexed variants
-# are all on indxed buffers like transform feedback buffers,
-# UBOs, or SSBOs, and querying their sizes and offsets.
 glGetIntegeri_v
     dir data out
     len data (sizeof(GLint))
@@ -1023,7 +787,6 @@
     var_flag data nullAllowed isLarge
 
 glTexImage3DOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glTexSubImage3D
@@ -1031,7 +794,6 @@
     var_flag data nullAllowed isLarge
 
 glTexSubImage3DOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glCompressedTexImage3D
@@ -1040,7 +802,6 @@
     var_flag data nullAllowed isLarge
 
 glCompressedTexImage3DOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glCompressedTexSubImage3D
@@ -1049,31 +810,25 @@
     var_flag data nullAllowed isLarge
 
 glCompressedTexSubImage3DOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glGetStringi
     flag unsupported
 
-# GLES 3.1
-
 glGetBooleani_v
     dir data out
     len data (sizeof(GLboolean))
 
 glGenProgramPipelines
-    flag custom_decoder
     dir pipelines out
     len pipelines (n * sizeof(GLuint))
 
 glDeleteProgramPipelines
-    flag custom_decoder
     len pipelines (n * sizeof(GLuint))
     param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; }
 
 glGetProgramPipelineiv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
 glGetProgramPipelineInfoLog
     dir infoLog out
@@ -1088,7 +843,6 @@
 
 glCreateShaderProgramvAEMU
     len packedStrings packedLen
-    flag custom_decoder
     flag not_api
 
 glProgramUniform1fv
@@ -1156,7 +910,6 @@
 
 glGetProgramInterfaceiv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
 glGetProgramResourceiv
     dir params out
@@ -1186,11 +939,9 @@
 
 glDrawArraysIndirectDataAEMU
     len indirect datalen
-    flag custom_decoder
     flag not_api
 
 glDrawArraysIndirectOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glDrawElementsIndirect
@@ -1198,218 +949,19 @@
 
 glDrawElementsIndirectDataAEMU
     len indirect datalen
-    flag custom_decoder
     flag not_api
 
 glDrawElementsIndirectOffsetAEMU
-    flag custom_decoder
     flag not_api
 
 glGetMultisamplefv
     dir val out
-    len val (glUtilsParamSize(pname) * sizeof(GLfloat))
 
 glGetFramebufferParameteriv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
 
 glGetTexLevelParameterfv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLfloat))
 
 glGetTexLevelParameteriv
     dir params out
-    len params (glUtilsParamSize(pname) * sizeof(GLint))
-glUseProgram
-    flag custom_decoder
-
-glValidateProgram
-    flag custom_decoder
-
-glIsProgram
-    flag custom_decoder
-
-glGetActiveAttrib
-    flag custom_decoder
-
-glGetActiveUniform
-    flag custom_decoder
-
-glGetAttachedShaders
-    flag custom_decoder
-
-glGetAttribLocation
-    flag custom_decoder
-
-glGetUniformfv
-    flag custom_decoder
-
-glGetUniformiv
-    flag custom_decoder
-
-glGetUniformLocation
-    flag custom_decoder
-
-glGetProgramBinaryOES
-    flag custom_decoder
-
-glProgramBinaryOES
-    flag custom_decoder
-
-glUniformBlockBinding
-    flag custom_decoder
-
-glGetUniformBlockIndex
-    flag custom_decoder
-
-glGetActiveUniformBlockiv
-    flag custom_decoder
-
-glGetActiveUniformBlockName
-    flag custom_decoder
-
-glGetUniformuiv
-    flag custom_decoder
-
-glGetActiveUniformsiv
-    flag custom_decoder
-
-glTransformFeedbackVaryings
-    flag custom_decoder
-
-glGetTransformFeedbackVarying
-    flag custom_decoder
-
-glProgramParameteri
-    flag custom_decoder
-
-glProgramBinary
-    flag custom_decoder
-
-glGetProgramBinary
-    flag custom_decoder
-
-glGetFragDataLocation
-    flag custom_decoder
-
-glUseProgramStages
-    flag custom_decoder
-
-glActiveShaderProgram
-    flag custom_decoder
-
-glProgramUniform1f
-    flag custom_decoder
-
-glProgramUniform2f
-    flag custom_decoder
-
-glProgramUniform3f
-    flag custom_decoder
-
-glProgramUniform4f
-    flag custom_decoder
-
-glProgramUniform1i
-    flag custom_decoder
-
-glProgramUniform2i
-    flag custom_decoder
-
-glProgramUniform3i
-    flag custom_decoder
-
-glProgramUniform4i
-    flag custom_decoder
-
-glProgramUniform1ui
-    flag custom_decoder
-
-glProgramUniform2ui
-    flag custom_decoder
-
-glProgramUniform3ui
-    flag custom_decoder
-
-glProgramUniform4ui
-    flag custom_decoder
-
-glProgramUniform1fv
-    flag custom_decoder
-
-glProgramUniform2fv
-    flag custom_decoder
-
-glProgramUniform3fv
-    flag custom_decoder
-
-glProgramUniform4fv
-    flag custom_decoder
-
-glProgramUniform1iv
-    flag custom_decoder
-
-glProgramUniform2iv
-    flag custom_decoder
-
-glProgramUniform3iv
-    flag custom_decoder
-
-glProgramUniform4iv
-    flag custom_decoder
-
-glProgramUniform1uiv
-    flag custom_decoder
-
-glProgramUniform2uiv
-    flag custom_decoder
-
-glProgramUniform3uiv
-    flag custom_decoder
-
-glProgramUniform4uiv
-    flag custom_decoder
-
-glProgramUniformMatrix2fv
-    flag custom_decoder
-
-glProgramUniformMatrix3fv
-    flag custom_decoder
-
-glProgramUniformMatrix4fv
-    flag custom_decoder
-
-glProgramUniformMatrix2x3fv
-    flag custom_decoder
-
-glProgramUniformMatrix3x2fv
-    flag custom_decoder
-
-glProgramUniformMatrix2x4fv
-    flag custom_decoder
-
-glProgramUniformMatrix4x2fv
-    flag custom_decoder
-
-glProgramUniformMatrix3x4fv
-    flag custom_decoder
-
-glProgramUniformMatrix4x3fv
-    flag custom_decoder
-
-glGetProgramInterfaceiv
-    flag custom_decoder
-
-glGetProgramResourceiv
-    flag custom_decoder
-
-glGetProgramResourceIndex
-    flag custom_decoder
-
-glGetProgramResourceLocation
-    flag custom_decoder
-
-glGetProgramResourceName
-    flag custom_decoder
-
-
diff --git a/host/libs/virglrenderer/GLESv3_dec/gles3.in b/host/libs/virglrenderer/GLESv3_dec/gles3.in
index 50d9406..33eb3b3 100644
--- a/host/libs/virglrenderer/GLESv3_dec/gles3.in
+++ b/host/libs/virglrenderer/GLESv3_dec/gles3.in
@@ -196,7 +196,7 @@
 GL_ENTRY(void, glExtGetTexLevelParameterivQCOM, GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params)
 GL_ENTRY(void, glExtTexObjectStateOverrideiQCOM, GLenum target, GLenum pname, GLint param)
 GL_ENTRY(void, glExtGetTexSubImageQCOM, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels)
-GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, GLvoidptr *params)
+GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, GLvoid** params)
 GL_ENTRY(void, glExtGetShadersQCOM, GLuint *shaders, GLint maxShaders, GLint *numShaders)
 GL_ENTRY(void, glExtGetProgramsQCOM, GLuint *programs, GLint maxPrograms, GLint *numPrograms)
 GL_ENTRY(GLboolean, glExtIsProgramBinaryQCOM, GLuint program)
@@ -309,7 +309,7 @@
 GL_ENTRY(GLuint, glGetUniformBlockIndex, GLuint program, const GLchar *uniformBlockName)
 
 # Assume uniformNames packed into 1 buffer on the guest.
-GL_ENTRY(void, glGetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar ** uniformNames, GLuint* uniformIndices)
+GL_ENTRY(void, glGetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar*const* uniformNames, GLuint* uniformIndices)
 GL_ENTRY(void, glGetUniformIndicesAEMU, GLuint program, GLsizei uniformCount, const GLchar *packedUniformNames, GLsizei packedLen, GLuint *uniformIndices)
 
 GL_ENTRY(void, glGetActiveUniformBlockiv, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
@@ -319,7 +319,7 @@
 GL_ENTRY(void, glUniform1ui, GLint location, GLuint v0)
 GL_ENTRY(void, glUniform2ui, GLint location, GLuint v0, GLuint v1)
 GL_ENTRY(void, glUniform3ui, GLint location, GLuint v0, GLuint v1, GLuint v2)
-GL_ENTRY(void, glUniform4ui, GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3)
+GL_ENTRY(void, glUniform4ui, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
 GL_ENTRY(void, glUniform1uiv, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glUniform2uiv, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glUniform3uiv, GLint location, GLsizei count, const GLuint *value)
@@ -399,7 +399,7 @@
 GL_ENTRY(void, glPauseTransformFeedback, void)
 GL_ENTRY(void, glResumeTransformFeedback, void)
 GL_ENTRY(GLboolean, glIsTransformFeedback, GLuint id)
-GL_ENTRY(void, glTransformFeedbackVaryings, GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode)
+GL_ENTRY(void, glTransformFeedbackVaryings, GLuint program, GLsizei count, const GLchar*const* varyings, GLenum bufferMode)
 GL_ENTRY(void, glTransformFeedbackVaryingsAEMU, GLuint program, GLsizei count, const char* packedVaryings, GLuint packedVaryingsLen, GLenum bufferMode)
 GL_ENTRY(void, glGetTransformFeedbackVarying, GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, char * name)
 
@@ -473,7 +473,7 @@
 
 # Separable shader programs - may need to change how program objects are represented and shared!
 GL_ENTRY(void, glActiveShaderProgram, GLuint pipeline, GLuint program);
-GL_ENTRY(GLuint, glCreateShaderProgramv, GLenum type, GLsizei count, const char ** strings)
+GL_ENTRY(GLuint, glCreateShaderProgramv, GLenum type, GLsizei count, const GLchar*const* strings)
 GL_ENTRY(GLuint, glCreateShaderProgramvAEMU, GLenum type, GLsizei count, const char *packedStrings, GLuint packedLen)
 # Uniforms should work easily if any program object representation problems are solved.
 GL_ENTRY(void, glProgramUniform1f, GLuint program, GLint location, GLfloat v0)
@@ -485,9 +485,9 @@
 GL_ENTRY(void, glProgramUniform3i, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
 GL_ENTRY(void, glProgramUniform4i, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
 GL_ENTRY(void, glProgramUniform1ui, GLuint program, GLint location, GLuint v0)
-GL_ENTRY(void, glProgramUniform2ui, GLuint program, GLint location, GLint v0, GLuint v1)
-GL_ENTRY(void, glProgramUniform3ui, GLuint program, GLint location, GLint v0, GLint v1, GLuint v2)
-GL_ENTRY(void, glProgramUniform4ui, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3)
+GL_ENTRY(void, glProgramUniform2ui, GLuint program, GLint location, GLuint v0, GLuint v1)
+GL_ENTRY(void, glProgramUniform3ui, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
+GL_ENTRY(void, glProgramUniform4ui, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
 GL_ENTRY(void, glProgramUniform1fv, 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, glProgramUniform3fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
@@ -529,7 +529,7 @@
 
 # Separate vertex format / buffer binding
 ### Requires us tp really clean up how draws work in the encoder currently.
-GL_ENTRY(void, glBindVertexBuffer, GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride)
+GL_ENTRY(void, glBindVertexBuffer, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride)
 GL_ENTRY(void, glVertexAttribBinding, GLuint attribindex, GLuint bindingindex);
 GL_ENTRY(void, glVertexAttribFormat, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset)
 GL_ENTRY(void, glVertexAttribIFormat, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)
diff --git a/host/libs/virglrenderer/GLESv3_dec/gles3_types.h b/host/libs/virglrenderer/GLESv3_dec/gles3_types.h
index bfff61d..3347b99 100644
--- a/host/libs/virglrenderer/GLESv3_dec/gles3_types.h
+++ b/host/libs/virglrenderer/GLESv3_dec/gles3_types.h
@@ -1,21 +1,19 @@
 /*
-* 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.
-*/
-#ifndef _GL_2_TYPES_H_
-#define _GL_2_TYPES_H_
-#include "gl_base_types.h"
+ * Copyright (C) 2018 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.
+ */
+#pragma once
 
-typedef void *GLvoidptr;
-#endif
+#include <GLES3/gl31.h>
+#include <GLES2/gl2ext.h>
diff --git a/host/libs/virglrenderer/Gralloc1.cpp b/host/libs/virglrenderer/Gralloc1.cpp
new file mode 100644
index 0000000..a2fcd81
--- /dev/null
+++ b/host/libs/virglrenderer/Gralloc1.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2018 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 <cstdint>
+
+extern "C" {
+#include "virgl_hw.h"
+}
+
+#include "Resource.h"
+
+#include <android/sync.h>
+#include <hardware/gralloc1.h>
+
+#include <cerrno>
+
+#define ALIGN(A, B) (((A) + (B)-1) / (B) * (B))
+
+static int gralloc1_device_open(const hw_module_t*, const char*, hw_device_t**);
+
+static hw_module_methods_t g_gralloc1_methods = {
+    .open = gralloc1_device_open,
+};
+
+static hw_module_t g_gralloc1_module = {
+    .tag = HARDWARE_MODULE_TAG,
+    .module_api_version = GRALLOC_MODULE_API_VERSION_1_0,
+    .hal_api_version = HARDWARE_HAL_API_VERSION,
+    .id = GRALLOC_HARDWARE_MODULE_ID,
+    .name = "AVDVirglRenderer",
+    .author = "Google",
+    .methods = &g_gralloc1_methods,
+};
+
+static int gralloc1_device_close(hw_device_t*) {
+    // No-op
+    return 0;
+}
+
+static void gralloc1_getCapabilities(gralloc1_device_t*, uint32_t* outCount, int32_t*) {
+    *outCount = 0U;
+}
+
+static int32_t gralloc1_lock(gralloc1_device_t*, buffer_handle_t buffer, uint64_t producerUsage,
+                             uint64_t consumerUsage, const gralloc1_rect_t* rect, void** outData,
+                             int32_t) {
+    uint32_t resource_id = (uint32_t) reinterpret_cast<uintptr_t>(buffer);
+    std::map<uint32_t, Resource*>::iterator it;
+    it = Resource::map.find(resource_id);
+    if (it == Resource::map.end())
+        return GRALLOC1_ERROR_BAD_HANDLE;
+
+    Resource* res = it->second;
+
+    // validate the lock rectangle
+    if (rect->width < 0 || rect->height < 0 || rect->left < 0 || rect->top < 0 ||
+        (uint32_t)rect->width + (uint32_t)rect->left > res->args.width ||
+        (uint32_t)rect->height + (uint32_t)rect->top > res->args.height) {
+        return GRALLOC1_ERROR_BAD_VALUE;
+    }
+
+    uint32_t bpp;
+    switch (res->args.format) {
+        case VIRGL_FORMAT_R8_UNORM:
+            bpp = 1U;
+            break;
+        case VIRGL_FORMAT_B5G6R5_UNORM:
+            bpp = 2U;
+            break;
+        default:
+            bpp = 4U;
+            break;
+    }
+    uint32_t stride = ALIGN(res->args.width * bpp, 16U);
+    *outData = (char*)res->linear + rect->top * stride + rect->left * bpp;
+    return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t gralloc1_unlock(gralloc1_device_t*, buffer_handle_t buffer,
+                               int32_t* outReleaseFence) {
+    uint32_t resource_id = (uint32_t) reinterpret_cast<uintptr_t>(buffer);
+    std::map<uint32_t, Resource*>::iterator it;
+    it = Resource::map.find(resource_id);
+    if (it == Resource::map.end())
+        return GRALLOC1_ERROR_BAD_HANDLE;
+    if (outReleaseFence)
+        *outReleaseFence = -1;
+
+    return GRALLOC1_ERROR_NONE;
+}
+
+static gralloc1_function_pointer_t gralloc1_getFunction(gralloc1_device_t*, int32_t descriptor) {
+    switch (descriptor) {
+        case GRALLOC1_FUNCTION_LOCK:
+            return reinterpret_cast<gralloc1_function_pointer_t>(&gralloc1_lock);
+        case GRALLOC1_FUNCTION_UNLOCK:
+            return reinterpret_cast<gralloc1_function_pointer_t>(&gralloc1_unlock);
+        default:
+            return nullptr;
+    }
+}
+
+static gralloc1_device_t g_gralloc1_device = {
+    .common =
+        {
+            .tag = HARDWARE_DEVICE_TAG,
+            .module = &g_gralloc1_module,
+            .close = gralloc1_device_close,
+        },
+    .getCapabilities = gralloc1_getCapabilities,
+    .getFunction = gralloc1_getFunction,
+};
+
+static int gralloc1_device_open(const hw_module_t* module, const char* id, hw_device_t** device) {
+    if (module != &g_gralloc1_module)
+        return -EINVAL;
+    if (strcmp(id, g_gralloc1_module.id))
+        return -EINVAL;
+    *device = &g_gralloc1_device.common;
+    return 0;
+}
+
+int hw_get_module(const char* id, const hw_module_t** module) {
+    if (strcmp(id, g_gralloc1_module.id))
+        return -EINVAL;
+    *module = const_cast<const hw_module_t*>(&g_gralloc1_module);
+    return 0;
+}
+
+int sync_wait(int, int) {
+    return 0;
+}
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/EGLDispatch.cpp b/host/libs/virglrenderer/OpenGLESDispatch/EGLDispatch.cpp
index f3de1bf..40cf7fc 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/EGLDispatch.cpp
+++ b/host/libs/virglrenderer/OpenGLESDispatch/EGLDispatch.cpp
@@ -1,56 +1,51 @@
 /*
-* 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.
-*/
-#include "OpenGLESDispatch/EGLDispatch.h"
+ * Copyright (C) 2018 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 "emugl/common/shared_library.h"
+#include <OpenGLESDispatch/EGLDispatch.h>
 
+#include <dlfcn.h>
 #include <stdio.h>
-#include <stdlib.h>
 
 EGLDispatch s_egl;
 
-#define DEFAULT_EGL_LIB EMUGL_LIBNAME("EGL_translator")
+#define DEFAULT_EGL_LIB "libEGL_swiftshader.so"
 
-#define RENDER_EGL_LOAD_FIELD(return_type, function_name, signature) \
-    s_egl. function_name = (function_name ## _t) lib->findSymbol(#function_name); \
+#define EGL_LOAD_FIELD(return_type, function_name, signature, callargs) \
+    s_egl.function_name = (function_name##_t)dlsym(handle, #function_name);
 
-#define RENDER_EGL_LOAD_FIELD_WITH_EGL(return_type, function_name, signature) \
-    if ((!s_egl. function_name) && s_egl.eglGetProcAddress) s_egl. function_name = \
-            (function_name ## _t) s_egl.eglGetProcAddress(#function_name); \
+#define EGL_LOAD_FIELD_WITH_EGL(return_type, function_name, signature, callargs) \
+    if ((!s_egl.function_name) && s_egl.eglGetProcAddress)                       \
+        s_egl.function_name = (function_name##_t)s_egl.eglGetProcAddress(#function_name);
 
-#define RENDER_EGL_LOAD_OPTIONAL_FIELD(return_type, function_name, signature) \
-    if (s_egl.eglGetProcAddress) s_egl. function_name = \
-            (function_name ## _t) s_egl.eglGetProcAddress(#function_name); \
-    if (!s_egl.function_name || !s_egl.eglGetProcAddress) \
-            RENDER_EGL_LOAD_FIELD(return_type, function_name, signature)
+#define EGL_LOAD_OPTIONAL_FIELD(return_type, function_name, signature, callargs)          \
+    if (s_egl.eglGetProcAddress)                                                          \
+        s_egl.function_name = (function_name##_t)s_egl.eglGetProcAddress(#function_name); \
+    if (!s_egl.function_name || !s_egl.eglGetProcAddress)                                 \
+    EGL_LOAD_FIELD(return_type, function_name, signature, callargs)
 
-bool init_egl_dispatch() {
-    const char *libName = getenv("ANDROID_EGL_LIB");
-    if (!libName) libName = DEFAULT_EGL_LIB;
-    char error[256];
-    emugl::SharedLibrary *lib = emugl::SharedLibrary::open(libName, error, sizeof(error));
-    if (!lib) {
-        printf("Failed to open %s: [%s]\n", libName, error);
+bool egl_dispatch_init() {
+    void* handle = dlopen(DEFAULT_EGL_LIB, RTLD_NOW);
+    if (!handle) {
+        printf("Failed to open %s\n", dlerror());
         return false;
     }
 
-    LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_LOAD_FIELD)
-    LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_LOAD_FIELD_WITH_EGL)
-    LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_LOAD_OPTIONAL_FIELD)
-    LIST_RENDER_EGL_SNAPSHOT_FUNCTIONS(RENDER_EGL_LOAD_FIELD)
+    LIST_EGL_FUNCTIONS(EGL_LOAD_FIELD)
+    LIST_EGL_FUNCTIONS(EGL_LOAD_FIELD_WITH_EGL)
+    LIST_EGL_EXTENSIONS_FUNCTIONS(EGL_LOAD_OPTIONAL_FIELD)
 
     return true;
 }
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/EGLDispatch.h b/host/libs/virglrenderer/OpenGLESDispatch/EGLDispatch.h
index 58102e9..eb3cd88 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/EGLDispatch.h
+++ b/host/libs/virglrenderer/OpenGLESDispatch/EGLDispatch.h
@@ -1,56 +1,41 @@
 /*
-* 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.
-*/
+ * Copyright (C) 2018 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.
+ */
+
 #pragma once
 
-#include "OpenGLESDispatch/RenderEGL_functions.h"
-#include "OpenGLESDispatch/RenderEGL_extensions_functions.h"
-#include "OpenGLESDispatch/RenderEGL_snapshot_functions.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
 
-// This header is used to define the EGLDispatch structure that contains
-// pointers to the EGL shared library used by libOpenglRender. Normally,
-// this will be our own libEGL_translator, but one could imagine a
-// vendor-specific being used instead.
+#include <OpenGLESDispatch/egl_functions.h>
+#include <OpenGLESDispatch/egl_extensions_functions.h>
 
-// There is a single global instance of this structure, named |s_egl|,
-// which must be initialized by calling init_egl_dispatch() before use.
+#define EGL_DEFINE_TYPE(return_type, function_name, signature, callargs) \
+    typedef return_type(EGLAPIENTRY* function_name##_t) signature;
 
-// Note that our code requires the implementation of misc EGL extensions
-// including eglSetSwapRectangleANDROID(), see RenderEGL_extensions_functions.h
-// for a full list.
+#define EGL_DECLARE_MEMBER(return_type, function_name, signature, callargs) \
+    function_name##_t function_name;
 
-#define RENDER_EGL_DEFINE_TYPE(return_type, function_name, signature) \
-    typedef return_type (EGLAPIENTRY *function_name ## _t) signature;
+LIST_EGL_FUNCTIONS(EGL_DEFINE_TYPE)
+LIST_EGL_EXTENSIONS_FUNCTIONS(EGL_DEFINE_TYPE)
 
-#define RENDER_EGL_DECLARE_MEMBER(return_type, function_name, signature) \
-    function_name ## _t function_name;
-
-// Define function typedefs.
-LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_DEFINE_TYPE)
-LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_DEFINE_TYPE)
-LIST_RENDER_EGL_SNAPSHOT_FUNCTIONS(RENDER_EGL_DEFINE_TYPE)
-
-// Define EGLDispatch structure.
 struct EGLDispatch {
-    LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER)
-    LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER)
-    LIST_RENDER_EGL_SNAPSHOT_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER)
+    LIST_EGL_FUNCTIONS(EGL_DECLARE_MEMBER)
+    LIST_EGL_EXTENSIONS_FUNCTIONS(EGL_DECLARE_MEMBER)
 };
 
-// Initialize EGLDispatch function. Return true on success, false on failure.
-bool init_egl_dispatch();
+bool egl_dispatch_init();
 
-// Global EGLDispatch instance. Call init_egl_dispatch() before using it.
 extern EGLDispatch s_egl;
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/GLESv1Dispatch.cpp b/host/libs/virglrenderer/OpenGLESDispatch/GLESv1Dispatch.cpp
index fd520cb..fd25afc 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/GLESv1Dispatch.cpp
+++ b/host/libs/virglrenderer/OpenGLESDispatch/GLESv1Dispatch.cpp
@@ -1,224 +1,42 @@
 /*
-* 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.
-*/
-#include "OpenGLESDispatch/GLESv1Dispatch.h"
+ * Copyright (C) 2018 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 "OpenGLESDispatch/EGLDispatch.h"
+#include <OpenGLESDispatch/EGLDispatch.h>
+#include <OpenGLESDispatch/GLESv1Dispatch.h>
 
-#include "android/utils/debug.h"
-
+#include <dlfcn.h>
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 
-#include "emugl/common/shared_library.h"
+#define DEFAULT_GLES_CM_LIB "libGLES_CM_swiftshader.so"
 
-#define DEBUG 0
+GLESv1Dispatch s_gles1;
 
-#if DEBUG
-#define DPRINT(...) do { \
-    if (!VERBOSE_CHECK(gles1emu)) VERBOSE_ENABLE(gles1emu); \
-    VERBOSE_PRINT(gles1emu, __VA_ARGS__); \
-} while (0)
-#else
-#define DPRINT(...)
-#endif
+#define LOOKUP_SYMBOL(return_type, function_name, signature, callargs)        \
+    s_gles1.function_name = (function_name##_t)dlsym(handle, #function_name); \
+    if ((!s_gles1.function_name) && s_egl.eglGetProcAddress)                  \
+        s_gles1.function_name = (function_name##_t)s_egl.eglGetProcAddress(#function_name);
 
-static emugl::SharedLibrary *s_gles1_lib = NULL;
-static emugl::SharedLibrary *s_underlying_gles2_lib = NULL;
-
-// An unimplemented function which prints out an error message.
-// To make it consistent with the guest, all GLES1 functions not supported by
-// the guest driver should be redirected to this function.
-
-void gles1_unimplemented() {
-    fprintf(stderr, "Called unimplemented GLESv1 API\n");
-}
-
-#define DEFAULT_GLES_CM_LIB EMUGL_LIBNAME("GLES_CM_translator")
-#define DEFAULT_UNDERLYING_GLES_V2_LIB EMUGL_LIBNAME("GLES_V2_translator")
-
-// This section of code (also in GLDispatch.cpp)
-// initializes all GLESv1 functions to dummy ones;
-// that is, in case we are using a library that doesn't
-// have GLESv1, we will still have stubs available to
-// signal that they are unsupported on the host.
-
-#define RETURN_void return
-#define RETURN_GLboolean return GL_FALSE
-#define RETURN_GLint return 0
-#define RETURN_GLuint return 0U
-#define RETURN_GLenum return 0
-#define RETURN_int return 0
-#define RETURN_GLconstubyteptr return NULL
-#define RETURN_voidptr return NULL
-
-#define RETURN_(x)  RETURN_ ## x
-
-#define DUMMY_MSG "Call to %s: host OpenGL driver does not support OpenGL ES v1. Skipping."
-
-#ifdef _WIN32
-
-#define DEFINE_DUMMY_FUNCTION(return_type, func_name, signature, args) \
-static return_type  __stdcall gles1_dummy_##func_name signature { \
-    fprintf(stderr, DUMMY_MSG, #func_name); \
-    RETURN_(return_type); \
-}
-
-#define DEFINE_DUMMY_EXTENSION_FUNCTION(return_type, func_name, signature, args) \
-static return_type __stdcall gles1_dummy_##func_name signature { \
-    fprintf(stderr, DUMMY_MSG, #func_name); \
-    RETURN_(return_type); \
-}
-
-#else
-
-#define DEFINE_DUMMY_FUNCTION(return_type, func_name, signature, args) \
-static return_type gles1_dummy_##func_name signature { \
-    fprintf(stderr, DUMMY_MSG, #func_name); \
-    RETURN_(return_type); \
-}
-
-#define DEFINE_DUMMY_EXTENSION_FUNCTION(return_type, func_name, signature, args) \
-static return_type gles1_dummy_##func_name signature { \
-    fprintf(stderr, DUMMY_MSG, #func_name); \
-    RETURN_(return_type); \
-}
-
-#endif
-
-LIST_GLES1_FUNCTIONS(DEFINE_DUMMY_FUNCTION, DEFINE_DUMMY_EXTENSION_FUNCTION);
-LIST_GLES12_TR_FUNCTIONS(DEFINE_DUMMY_FUNCTION);
-
-//
-// This function is called only once during initialiation before
-// any thread has been created - hence it should NOT be thread safe.
-//
-
-//
-// init dummy GLESv1 dispatch table
-//
-#define ASSIGN_DUMMY(return_type,function_name,signature,callargs) do { \
-        dispatch_table-> function_name = gles1_dummy_##function_name; \
-        } while(0);
-
-bool gles1_dispatch_init(GLESv1Dispatch* dispatch_table) {
-
-    dispatch_table->underlying_gles2_api = NULL;
-
-    const char* libName = getenv("ANDROID_GLESv1_LIB");
-    if (!libName) {
-        libName = DEFAULT_GLES_CM_LIB;
+bool gles1_dispatch_init() {
+    void* handle = dlopen(DEFAULT_GLES_CM_LIB, RTLD_NOW);
+    if (!handle) {
+        printf("Failed to open %s\n", dlerror());
+        return false;
     }
 
-    // If emugl_config has detected specifically a backend
-    // that supports only GLESv2, set GLESv1 entry points
-    // to the dummy functions.
-    if (!strcmp(libName, "<gles2_only_backend>")) {
+    LIST_GLES1_FUNCTIONS(LOOKUP_SYMBOL, LOOKUP_SYMBOL)
 
-        LIST_GLES1_FUNCTIONS(ASSIGN_DUMMY,ASSIGN_DUMMY)
-
-        DPRINT("assigning dummies because <gles2_only_backend>");
-        return true;
-    } else {
-
-        char error[256];
-        s_gles1_lib = emugl::SharedLibrary::open(libName, error, sizeof(error));
-        if (!s_gles1_lib) {
-            fprintf(stderr, "%s: Could not load %s [%s]\n", __FUNCTION__,
-                    libName, error);
-            return false;
-        }
-
-        //
-        // init the GLES dispatch table
-        //
-#define LOOKUP_SYMBOL(return_type,function_name,signature,callargs) do { \
-        dispatch_table-> function_name = reinterpret_cast< function_name ## _t >( \
-                s_gles1_lib->findSymbol(#function_name)); \
-            if ((!dispatch_table-> function_name) && s_egl.eglGetProcAddress) \
-            dispatch_table-> function_name = reinterpret_cast< function_name ## _t >( \
-                s_egl.eglGetProcAddress(#function_name)); \
-        } while(0); \
-
-        LIST_GLES1_FUNCTIONS(LOOKUP_SYMBOL,LOOKUP_SYMBOL)
-
-        DPRINT("successful");
-
-        LIST_GLES12_TR_FUNCTIONS(ASSIGN_DUMMY);
-
-        // If we are using the translator,
-        // import the gles1->2 translator dll
-        if (strstr(libName, "GLES12Translator")) {
-
-            DPRINT("trying to assign gles12-specific functions");
-            LIST_GLES12_TR_FUNCTIONS(LOOKUP_SYMBOL);
-            DPRINT("hopefully, successfully assigned "
-                   "12tr-specific functions...");
-
-            DPRINT("Now creating the underlying api");
-            UnderlyingApis* gles2api =
-                (UnderlyingApis*)dispatch_table->create_underlying_api();
-            dispatch_table->underlying_gles2_api = gles2api;
-
-            DPRINT("api ptr:%p", dispatch_table->underlying_gles2_api);
-
-#define SET_UNDERLYING_GLES2_FUNC(rett, function_name, sig, callargs) do { \
-    dispatch_table->underlying_gles2_api->angle-> function_name = \
-        reinterpret_cast< function_name ## _t >( \
-                s_underlying_gles2_lib->findSymbol(#function_name)); \
-} while(0);
-
-            DPRINT("trying to initialize GLESv1->2 translation");
-            const char* underlying_gles2_lib_name =
-                getenv("ANDROID_GLESv2_LIB");
-
-            if (!underlying_gles2_lib_name) {
-                underlying_gles2_lib_name = DEFAULT_UNDERLYING_GLES_V2_LIB;
-            }
-            s_underlying_gles2_lib =
-                emugl::SharedLibrary::open(underlying_gles2_lib_name,
-                                           error, sizeof(error));
-            if (!s_underlying_gles2_lib) {
-                DPRINT("Could not load underlying gles2 lib %s [%s]",
-                        libName, error);
-                return false;
-            }
-            DPRINT("done trying to get gles2 lib");
-
-            LIST_GLES2_FUNCTIONS(SET_UNDERLYING_GLES2_FUNC,
-                                 SET_UNDERLYING_GLES2_FUNC);
-       }
-       return true;
-    }
-}
-
-//
-// This function is called only during initialization of the decoder before
-// any thread has been created - hence it should NOT be thread safe.
-//
-void *gles1_dispatch_get_proc_func(const char *name, void *userData)
-{
-    void* func = NULL;
-    if (s_gles1_lib) {
-        func = (void *)s_gles1_lib->findSymbol(name);
-    }
-    // To make it consistent with the guest, redirect any unsupported functions
-    // to gles1_unimplemented.
-    if (!func) {
-        func = (void *)gles1_unimplemented;
-    }
-    return func;
+    return true;
 }
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/GLESv1Dispatch.h b/host/libs/virglrenderer/OpenGLESDispatch/GLESv1Dispatch.h
index ad71f81..b65b83c 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/GLESv1Dispatch.h
+++ b/host/libs/virglrenderer/OpenGLESDispatch/GLESv1Dispatch.h
@@ -1,49 +1,40 @@
 /*
-* 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.
-*/
+ * Copyright (C) 2018 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.
+ */
+
 #pragma once
 
-#include "OpenGLESDispatch/gldefs.h"
-#include "OpenGLESDispatch/gles_functions.h"
-#include "KHR/khrplatform.h"
+#include <GLES/gl.h>
 
-#include "GLES12Translator/underlying_apis.h"
+#include <OpenGLESDispatch/gles_functions.h>
 
-// Define function pointer types.
-#define GLES1_DISPATCH_DEFINE_TYPE(return_type,func_name,signature,callargs) \
-    typedef return_type (KHRONOS_APIENTRY * func_name ## _t) signature;
+#define GLES1_DISPATCH_DEFINE_TYPE(return_type, func_name, signature, callargs) \
+    typedef return_type(KHRONOS_APIENTRY* func_name##_t) signature;
 
-LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DEFINE_TYPE,GLES1_DISPATCH_DEFINE_TYPE)
-    LIST_GLES12_TR_FUNCTIONS(GLES1_DISPATCH_DEFINE_TYPE)
+#define GLES1_DISPATCH_DECLARE_POINTER(return_type, func_name, signature, callargs) \
+    func_name##_t func_name;
+
+LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DEFINE_TYPE, GLES1_DISPATCH_DEFINE_TYPE)
 
 struct GLESv1Dispatch {
-#define GLES1_DISPATCH_DECLARE_POINTER(return_type,func_name,signature,callargs) \
-        func_name ## _t func_name;
-    LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DECLARE_POINTER,
-                         GLES1_DISPATCH_DECLARE_POINTER)
-    LIST_GLES12_TR_FUNCTIONS(GLES1_DISPATCH_DECLARE_POINTER)
-    UnderlyingApis* underlying_gles2_api;
+    LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DECLARE_POINTER, GLES1_DISPATCH_DECLARE_POINTER)
 };
 
-#undef GLES1_DISPATCH_DECLARE_POINTER
 #undef GLES1_DISPATCH_DEFINE_TYPE
+#undef GLES1_DISPATCH_DECLARE_POINTER
 
-bool gles1_dispatch_init(GLESv1Dispatch* dispatch_table);
+bool gles1_dispatch_init();
 
-// Used to initialize the decoder.
-void* gles1_dispatch_get_proc_func(const char* name, void* userData);
-
-// Used to check for unimplemented.
-void gles1_unimplemented();
+extern GLESv1Dispatch s_gles1;
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/GLESv3Dispatch.cpp b/host/libs/virglrenderer/OpenGLESDispatch/GLESv3Dispatch.cpp
index 24b7301..4aaa518 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/GLESv3Dispatch.cpp
+++ b/host/libs/virglrenderer/OpenGLESDispatch/GLESv3Dispatch.cpp
@@ -1,88 +1,42 @@
 /*
-* 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.
-*/
-#include "OpenGLESDispatch/GLESv2Dispatch.h"
+ * Copyright (C) 2018 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 "OpenGLESDispatch/EGLDispatch.h"
+#include <OpenGLESDispatch/EGLDispatch.h>
+#include <OpenGLESDispatch/GLESv3Dispatch.h>
 
+#include <dlfcn.h>
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 
-#include "emugl/common/shared_library.h"
+#define DEFAULT_GLESv2_LIB "libGLESv2_swiftshader.so"
 
-static emugl::SharedLibrary *s_gles2_lib = NULL;
+GLESv3Dispatch s_gles3;
 
-#define DEFAULT_GLES_V2_LIB EMUGL_LIBNAME("GLES_V2_translator")
+#define LOOKUP_SYMBOL(return_type, function_name, signature, callargs)        \
+    s_gles3.function_name = (function_name##_t)dlsym(handle, #function_name); \
+    if ((!s_gles3.function_name) && s_egl.eglGetProcAddress)                  \
+        s_gles3.function_name = (function_name##_t)s_egl.eglGetProcAddress(#function_name);
 
-// An unimplemented function which prints out an error message.
-// To make it consistent with the guest, all GLES2 functions not supported by
-// the driver should be redirected to this function.
-
-void gles2_unimplemented() {
-    fprintf(stderr, "Called unimplemented GLES API\n");
-}
-
-//
-// This function is called only once during initialiation before
-// any thread has been created - hence it should NOT be thread safe.
-//
-bool gles2_dispatch_init(GLESv2Dispatch* dispatch_table)
-{
-    const char *libName = getenv("ANDROID_GLESv2_LIB");
-    if (!libName) {
-        libName = DEFAULT_GLES_V2_LIB;
-    }
-
-    char error[256];
-    s_gles2_lib = emugl::SharedLibrary::open(libName, error, sizeof(error));
-    if (!s_gles2_lib) {
-        fprintf(stderr, "%s: Could not load %s [%s]\n", __FUNCTION__,
-                libName, error);
+bool gles3_dispatch_init() {
+    void* handle = dlopen(DEFAULT_GLESv2_LIB, RTLD_NOW);
+    if (!handle) {
+        printf("Failed to open %s\n", dlerror());
         return false;
     }
 
-    //
-    // init the GLES dispatch table
-    //
-#define LOOKUP_SYMBOL(return_type,function_name,signature,callargs) \
-    dispatch_table-> function_name = reinterpret_cast< function_name ## _t >( \
-            s_gles2_lib->findSymbol(#function_name)); \
-    if ((!dispatch_table-> function_name) && s_egl.eglGetProcAddress) \
-        dispatch_table-> function_name = reinterpret_cast< function_name ## _t >( \
-            s_egl.eglGetProcAddress(#function_name)); \
-
-    LIST_GLES2_FUNCTIONS(LOOKUP_SYMBOL,LOOKUP_SYMBOL)
+    LIST_GLES3_FUNCTIONS(LOOKUP_SYMBOL, LOOKUP_SYMBOL)
 
     return true;
 }
-
-//
-// This function is called only during initialization before
-// any thread has been created - hence it should NOT be thread safe.
-//
-void *gles2_dispatch_get_proc_func(const char *name, void *userData)
-{
-    void* func = NULL;
-    if (s_gles2_lib) {
-        func = (void *)s_gles2_lib->findSymbol(name);
-    }
-    // To make it consistent with the guest, redirect any unsupported functions
-    // to gles2_unimplemented.
-    if (!func) {
-        func = (void *)gles2_unimplemented;
-    }
-    return func;
-}
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/GLESv3Dispatch.h b/host/libs/virglrenderer/OpenGLESDispatch/GLESv3Dispatch.h
index 0084156..afdd000 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/GLESv3Dispatch.h
+++ b/host/libs/virglrenderer/OpenGLESDispatch/GLESv3Dispatch.h
@@ -1,56 +1,41 @@
 /*
-* 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.
-*/
+ * Copyright (C) 2018 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.
+ */
+
 #pragma once
 
-#include "OpenGLESDispatch/gldefs.h"
-#include "OpenGLESDispatch/gles_functions.h"
-#include "KHR/khrplatform.h"
+#include <GLES3/gl31.h>
+
+#include <OpenGLESDispatch/gles_functions.h>
 
 // Define function pointer types.
-#define GLES2_DISPATCH_DEFINE_TYPE(return_type,func_name,signature,callargs) \
-    typedef return_type (KHRONOS_APIENTRY * func_name ## _t) signature;
+#define GLES3_DISPATCH_DEFINE_TYPE(return_type, func_name, signature, callargs) \
+    typedef return_type(KHRONOS_APIENTRY* func_name##_t) signature;
 
-LIST_GLES2_FUNCTIONS(GLES2_DISPATCH_DEFINE_TYPE,GLES2_DISPATCH_DEFINE_TYPE)
+#define GLES3_DISPATCH_DECLARE_POINTER(return_type, func_name, signature, callargs) \
+    func_name##_t func_name;
 
-struct GLESv2Dispatch {
-#define GLES2_DISPATCH_DECLARE_POINTER(return_type,func_name,signature,callargs) \
-        func_name ## _t func_name;
-    LIST_GLES2_FUNCTIONS(GLES2_DISPATCH_DECLARE_POINTER,
-                         GLES2_DISPATCH_DECLARE_POINTER)
+LIST_GLES3_FUNCTIONS(GLES3_DISPATCH_DEFINE_TYPE, GLES3_DISPATCH_DEFINE_TYPE)
+
+struct GLESv3Dispatch {
+    LIST_GLES3_FUNCTIONS(GLES3_DISPATCH_DECLARE_POINTER, GLES3_DISPATCH_DECLARE_POINTER)
 };
 
-#undef GLES2_DISPATCH_DECLARE_POINTER
-#undef GLES2_DISPATCH_DEFINE_TYPE
+#undef GLES3_DISPATCH_DEFINE_TYPE
+#undef GLES3_DISPATCH_DECLARE_POINTER
 
-bool gles2_dispatch_init(GLESv2Dispatch* dispatch_table);
+bool gles3_dispatch_init();
 
-// Used to initialize the decoder.
-void* gles2_dispatch_get_proc_func(const char* name, void* userData);
-// Used to check for unimplemented.
-void gles2_unimplemented();
-
-// Used to query max GLES version support based on what the dispatch mechanism
-// has found in the GLESv2 library.
-// First, a enum for tracking the detected GLES version based on dispatch.
-// We support 2 minimally.
-enum GLESDispatchMaxVersion {
-    GLES_DISPATCH_MAX_VERSION_2 = 0,
-    GLES_DISPATCH_MAX_VERSION_3_0 = 1,
-    GLES_DISPATCH_MAX_VERSION_3_1 = 2,
-    GLES_DISPATCH_MAX_VERSION_3_2 = 3,
-};
-
-GLESDispatchMaxVersion gles2_dispatch_get_max_version();
+extern GLESv3Dispatch s_gles3;
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/egl.entries b/host/libs/virglrenderer/OpenGLESDispatch/egl.entries
index e6279a3..46d4c0d 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/egl.entries
+++ b/host/libs/virglrenderer/OpenGLESDispatch/egl.entries
@@ -1,28 +1,44 @@
-# The list of EGL functions used by libOpenglRender, without extensions.
-# This is only a subset of the full EGL API.
+!egl
 
-!Render_EGL
 %#include <EGL/egl.h>
 
+%// Return types must be single words, see GLDispatch.cpp
+%typedef const char* EGLconstcharptr;
+
+EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
+EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
+EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLDisplay eglGetCurrentDisplay(void);
+EGLSurface eglGetCurrentSurface(EGLint readdraw);
+EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id);
 EGLint eglGetError(void);
-EGLDisplay eglGetDisplay(EGLNativeDisplayType dpy);
+void* eglGetProcAddress(const char *procname);
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+EGLconstcharptr eglQueryString(EGLDisplay dpy, EGLint name);
+EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
 EGLBoolean eglTerminate(EGLDisplay dpy);
-EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor);
-char* eglQueryString(EGLDisplay dpy, EGLint id);
-EGLBoolean eglGetConfigs(EGLDisplay display, EGLConfig* configs, EGLint config_size, EGLint* num_config);
-EGLBoolean eglChooseConfig(EGLDisplay display, const EGLint* attribs, EGLConfig* configs, EGLint config_size, EGLint* num_config);
-EGLBoolean eglGetConfigAttrib(EGLDisplay display, EGLConfig config, EGLint attribute, EGLint* value);
-EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, EGLNativeWindowType native_window, const EGLint* attrib_list);
-EGLSurface eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, const EGLint* attrib_list);
-EGLBoolean eglDestroySurface(EGLDisplay display, EGLSurface surface);
+EGLBoolean eglWaitGL(void);
+EGLBoolean eglWaitNative(EGLint engine);
+
+EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval);
+
 EGLBoolean eglBindAPI(EGLenum api);
 EGLenum eglQueryAPI(void);
+EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
 EGLBoolean eglReleaseThread(void);
-EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, const EGLint* attrib_list);
-EGLBoolean eglDestroyContext(EGLDisplay display, EGLContext context);
-EGLBoolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context);
+EGLBoolean eglWaitClient(void);
+
 EGLContext eglGetCurrentContext(void);
-EGLSurface eglGetCurrentSurface(EGLint readdraw);
-EGLBoolean eglQuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint *value);
-EGLBoolean eglSwapBuffers(EGLDisplay display, EGLSurface surface);
-void* eglGetProcAddress(const char* function_name);
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/egl_extensions.entries b/host/libs/virglrenderer/OpenGLESDispatch/egl_extensions.entries
index 186f1f0..e1e0bc7 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/egl_extensions.entries
+++ b/host/libs/virglrenderer/OpenGLESDispatch/egl_extensions.entries
@@ -1,19 +1,11 @@
-# The list of EGL extension functions used by libOpenglRender.
-# This is only a subset of the full EGL API.
+!egl_extensions
 
-!Render_EGL_extensions
-
-%#include <EGL/egl.h>
-%#define EGL_EGLEXT_PROTOTYPES
 %#include <EGL/eglext.h>
 
-EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list);
-EGLBoolean eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image);
-EGLSyncKHR eglCreateSyncKHR(EGLDisplay display, EGLenum type, const EGLint* attribs);
-EGLint eglClientWaitSyncKHR(EGLDisplay display, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
-EGLint eglWaitSyncKHR(EGLDisplay display, EGLSyncKHR sync, EGLint flags);
-EGLBoolean eglDestroySyncKHR(EGLDisplay display, EGLSyncKHR sync);
-EGLint eglGetMaxGLESVersion(EGLDisplay display);
-void eglBlitFromCurrentReadBufferANDROID(EGLDisplay display, EGLImageKHR image);
-void* eglSetImageFenceANDROID(EGLDisplay display, EGLImageKHR image);
-void eglWaitImageFenceANDROID(EGLDisplay display, void* fence);
+EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);
+EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image);
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/gles1_core.entries b/host/libs/virglrenderer/OpenGLESDispatch/gles1_core.entries
index f42e279..8c7f953 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/gles1_core.entries
+++ b/host/libs/virglrenderer/OpenGLESDispatch/gles1_core.entries
@@ -1,16 +1,153 @@
-!gles12_tr
+!gles1_core
 
-# Functions which are needed ONLY for implementing GLES 1->2 translation
+%#include <GLES/gl.h>
 
-%typedef void* voidptr;
+%// Return types must be single words, see GLDispatch.cpp
+%typedef const GLubyte* GL1constubyteptr;
 
-voidptr create_gles1_context(void* share, const void* underlying_apis);
-voidptr get_current_gles_context(void);
-void set_current_gles_context(void* ctx);
-voidptr create_underlying_api(void);
+void glAlphaFunc(GLenum func, GLclampf ref);
+void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+void glClearDepthf(GLclampf depth);
+void glClipPlanef(GLenum plane, const GLfloat *equation);
+void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void glDepthRangef(GLclampf zNear, GLclampf zFar);
+void glFogf(GLenum pname, GLfloat param);
+void glFogfv(GLenum pname, const GLfloat *params);
+void glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+void glGetClipPlanef(GLenum pname, GLfloat *eqn);
+void glGetFloatv(GLenum pname, GLfloat *params);
+void glGetLightfv(GLenum light, GLenum pname, GLfloat *params);
+void glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params);
+void glGetTexEnvfv(GLenum env, GLenum pname, GLfloat *params);
+void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
+void glLightModelf(GLenum pname, GLfloat param);
+void glLightModelfv(GLenum pname, const GLfloat *params);
+void glLightf(GLenum light, GLenum pname, GLfloat param);
+void glLightfv(GLenum light, GLenum pname, const GLfloat *params);
+void glLineWidth(GLfloat width);
+void glLoadMatrixf(const GLfloat *m);
+void glMaterialf(GLenum face, GLenum pname, GLfloat param);
+void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
+void glMultMatrixf(const GLfloat *m);
+void glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
+void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+void glPointParameterf(GLenum pname, GLfloat param);
+void glPointParameterfv(GLenum pname, const GLfloat *params);
+void glPointSize(GLfloat size);
+void glPolygonOffset(GLfloat factor, GLfloat units);
+void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+void glScalef(GLfloat x, GLfloat y, GLfloat z);
+void glTexEnvf(GLenum target, GLenum pname, GLfloat param);
+void glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params);
+void glTexParameterf(GLenum target, GLenum pname, GLfloat param);
+void glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params);
+void glTranslatef(GLfloat x, GLfloat y, GLfloat z);
+void glActiveTexture(GLenum texture);
+void glAlphaFuncx(GLenum func, GLclampx ref);
+void glBindBuffer(GLenum target, GLuint buffer);
+void glBindTexture(GLenum target, GLuint texture);
+void glBlendFunc(GLenum sfactor, GLenum dfactor);
+void glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+void glClear(GLbitfield mask);
+void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha);
+void glClearDepthx(GLclampx depth);
+void glClearStencil(GLint s);
+void glClientActiveTexture(GLenum texture);
+void glClipPlanex(GLenum plane, const GLfixed *equation);
+void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+void glColor4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void glCullFace(GLenum mode);
+void glDeleteBuffers(GLsizei n, const GLuint *buffers);
+void glDeleteTextures(GLsizei n, const GLuint *textures);
+void glDepthFunc(GLenum func);
+void glDepthMask(GLboolean flag);
+void glDepthRangex(GLclampx zNear, GLclampx zFar);
+void glDisable(GLenum cap);
+void glDisableClientState(GLenum array);
+void glDrawArrays(GLenum mode, GLint first, GLsizei count);
+void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+void glEnable(GLenum cap);
+void glEnableClientState(GLenum array);
+void glFinish(void);
+void glFlush(void);
+void glFogx(GLenum pname, GLfixed param);
+void glFogxv(GLenum pname, const GLfixed *params);
+void glFrontFace(GLenum mode);
+void glFrustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+void glGetBooleanv(GLenum pname, GLboolean *params);
+void glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params);
+void glGetClipPlanex(GLenum pname, GLfixed *eqn);
+void glGenBuffers(GLsizei n, GLuint *buffers);
+void glGenTextures(GLsizei n, GLuint *textures);
+GLenum glGetError(void);
+void glGetFixedv(GLenum pname, GLfixed *params);
+void glGetIntegerv(GLenum pname, GLint *params);
+void glGetLightxv(GLenum light, GLenum pname, GLfixed *params);
+void glGetMaterialxv(GLenum face, GLenum pname, GLfixed *params);
+void glGetPointerv(GLenum pname, GLvoid **params);
+GL1constubyteptr glGetString(GLenum name);
+void glGetTexEnviv(GLenum env, GLenum pname, GLint *params);
+void glGetTexEnvxv(GLenum env, GLenum pname, GLfixed *params);
+void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params);
+void glGetTexParameterxv(GLenum target, GLenum pname, GLfixed *params);
+void glHint(GLenum target, GLenum mode);
+GLboolean glIsBuffer(GLuint buffer);
+GLboolean glIsEnabled(GLenum cap);
+GLboolean glIsTexture(GLuint texture);
+void glLightModelx(GLenum pname, GLfixed param);
+void glLightModelxv(GLenum pname, const GLfixed *params);
+void glLightx(GLenum light, GLenum pname, GLfixed param);
+void glLightxv(GLenum light, GLenum pname, const GLfixed *params);
+void glLineWidthx(GLfixed width);
+void glLoadIdentity(void);
+void glLoadMatrixx(const GLfixed *m);
+void glLogicOp(GLenum opcode);
+void glMaterialx(GLenum face, GLenum pname, GLfixed param);
+void glMaterialxv(GLenum face, GLenum pname, const GLfixed *params);
+void glMatrixMode(GLenum mode);
+void glMultMatrixx(const GLfixed *m);
+void glMultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+void glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz);
+void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer);
+void glOrthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+void glPixelStorei(GLenum pname, GLint param);
+void glPointParameterx(GLenum pname, GLfixed param);
+void glPointParameterxv(GLenum pname, const GLfixed *params);
+void glPointSizex(GLfixed size);
+void glPolygonOffsetx(GLfixed factor, GLfixed units);
+void glPopMatrix(void);
+void glPushMatrix(void);
+void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+void glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+void glSampleCoverage(GLclampf value, GLboolean invert);
+void glSampleCoveragex(GLclampx value, GLboolean invert);
+void glScalex(GLfixed x, GLfixed y, GLfixed z);
+void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
+void glShadeModel(GLenum mode);
+void glStencilFunc(GLenum func, GLint ref, GLuint mask);
+void glStencilMask(GLuint mask);
+void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);
+void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void glTexEnvi(GLenum target, GLenum pname, GLint param);
+void glTexEnvx(GLenum target, GLenum pname, GLfixed param);
+void glTexEnviv(GLenum target, GLenum pname, const GLint *params);
+void glTexEnvxv(GLenum target, GLenum pname, const GLfixed *params);
+void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void glTexParameteri(GLenum target, GLenum pname, GLint param);
+void glTexParameterx(GLenum target, GLenum pname, GLfixed param);
+void glTexParameteriv(GLenum target, GLenum pname, const GLint *params);
+void glTexParameterxv(GLenum target, GLenum pname, const GLfixed *params);
+void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void glTranslatex(GLfixed x, GLfixed y, GLfixed z);
+void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
 
-# Extra setup on making a emulated GLES1 context current
-void make_current_setup(uint32_t surf_width, uint32_t surf_height);
-
-# destroying GLES1 contexts
-void destroy_gles1_context(void* ctx);
+void glPointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer);
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/gles1_extensions.entries b/host/libs/virglrenderer/OpenGLESDispatch/gles1_extensions.entries
index 2670bae..a2e990a 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/gles1_extensions.entries
+++ b/host/libs/virglrenderer/OpenGLESDispatch/gles1_extensions.entries
@@ -1,17 +1,35 @@
 !gles1_extensions
 
-# OpenGL functions which are needed ONLY for implementing GLES 1.1 EXTENSIONS
-void glCurrentPaletteMatrixARB(GLint index);
-void glMatrixIndexuivARB(GLint size, GLuint * indices);
-void glMatrixIndexPointerARB(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
-void glWeightPointerARB(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
-void glTexGenf(GLenum coord, GLenum pname, GLfloat param );
-void glTexGeni(GLenum coord, GLenum pname, GLint param );
-void glTexGenfv(GLenum coord, GLenum pname, const GLfloat *params );
-void glTexGeniv(GLenum coord, GLenum pname, const GLint *params );
-void glGetTexGenfv(GLenum coord, GLenum pname, GLfloat *params );
-void glGetTexGeniv(GLenum coord, GLenum pname, GLint *params );
-void glColorPointerWithDataSize(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer, GLsizei dataSize);
-void glNormalPointerWithDataSize(GLenum type, GLsizei stride, const GLvoid *pointer, GLsizei dataSize);
-void glTexCoordPointerWithDataSize(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer, GLsizei dataSize);
-void glVertexPointerWithDataSize(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer, GLsizei dataSize);
+%#include <GLES/glext.h>
+
+void glBlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha);
+void glBlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+void glBlendEquationOES(GLenum mode);
+
+void glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height);
+void glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height);
+void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height);
+void glDrawTexsvOES(const GLshort *coords);
+void glDrawTexivOES(const GLint *coords);
+void glDrawTexxvOES(const GLfixed *coords);
+void glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);
+void glDrawTexfvOES(const GLfloat *coords);
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
+
+GLboolean glIsRenderbufferOES(GLuint renderbuffer);
+void glBindRenderbufferOES(GLenum target, GLuint renderbuffer);
+void glDeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers);
+void glGenRenderbuffersOES(GLsizei n, GLuint* renderbuffers);
+void glRenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+void glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params);
+GLboolean glIsFramebufferOES(GLuint framebuffer);
+void glBindFramebufferOES(GLenum target, GLuint framebuffer);
+void glDeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers);
+void glGenFramebuffersOES(GLsizei n, GLuint* framebuffers);
+GLenum glCheckFramebufferStatusOES(GLenum target);
+void glFramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+void glFramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+void glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params);
+void glGenerateMipmapOES(GLenum target);
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/gles2_core.entries b/host/libs/virglrenderer/OpenGLESDispatch/gles2_core.entries
index 0eaa0ae..6cab5f8 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/gles2_core.entries
+++ b/host/libs/virglrenderer/OpenGLESDispatch/gles2_core.entries
@@ -1,85 +1,146 @@
-!gles2_only
+!gles2_core
 
-# OpenGL functions which are needed ONLY for implementing GLES 2.0
-void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
-void glStencilMaskSeparate(GLenum face, GLuint mask);
-void glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
-GLboolean glIsProgram(GLuint program);
-GLboolean glIsShader(GLuint shader);
-void glVertexAttrib1f(GLuint indx, GLfloat x);
-void glVertexAttrib1fv(GLuint indx, const GLfloat* values);
-void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
-void glVertexAttrib2fv(GLuint indx, const GLfloat* values);
-void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
-void glVertexAttrib3fv(GLuint indx, const GLfloat* values);
-void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void glVertexAttrib4fv(GLuint indx, const GLfloat* values);
-void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
-void glDisableVertexAttribArray(GLuint index);
-void glEnableVertexAttribArray(GLuint index);
-void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
-void glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
-void glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer);
-void glUniform1f(GLint location, GLfloat x);
-void glUniform1fv(GLint location, GLsizei count, const GLfloat* v);
-void glUniform1i(GLint location, GLint x);
-void glUniform1iv(GLint location, GLsizei count, const GLint* v);
-void glUniform2f(GLint location, GLfloat x, GLfloat y);
-void glUniform2fv(GLint location, GLsizei count, const GLfloat* v);
-void glUniform2i(GLint location, GLint x, GLint y);
-void glUniform2iv(GLint location, GLsizei count, const GLint* v);
-void glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z);
-void glUniform3fv(GLint location, GLsizei count, const GLfloat* v);
-void glUniform3i(GLint location, GLint x, GLint y, GLint z);
-void glUniform3iv(GLint location, GLsizei count, const GLint* v);
-void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void glUniform4fv(GLint location, GLsizei count, const GLfloat* v);
-void glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w);
-void glUniform4iv(GLint location, GLsizei count, const GLint* v);
-void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+%#include <GLES3/gl31.h>
+
+void glActiveTexture(GLenum texture);
 void glAttachShader(GLuint program, GLuint shader);
-void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name);
+void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name);
+void glBindBuffer(GLenum target, GLuint buffer);
+void glBindFramebuffer(GLenum target, GLuint framebuffer);
+void glBindRenderbuffer(GLenum target, GLuint renderbuffer);
+void glBindTexture(GLenum target, GLuint texture);
+void glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void glBlendEquation(GLenum mode);
+void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
+void glBlendFunc(GLenum sfactor, GLenum dfactor);
+void glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GLenum glCheckFramebufferStatus(GLenum target);
+void glClear(GLbitfield mask);
+void glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void glClearDepthf(GLfloat d);
+void glClearStencil(GLint s);
+void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
 void glCompileShader(GLuint shader);
+void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 GLuint glCreateProgram(void);
 GLuint glCreateShader(GLenum type);
+void glCullFace(GLenum mode);
+void glDeleteBuffers(GLsizei n, const GLuint *buffers);
+void glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers);
 void glDeleteProgram(GLuint program);
+void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers);
 void glDeleteShader(GLuint shader);
+void glDeleteTextures(GLsizei n, const GLuint *textures);
+void glDepthFunc(GLenum func);
+void glDepthMask(GLboolean flag);
+void glDepthRangef(GLfloat n, GLfloat f);
 void glDetachShader(GLuint program, GLuint shader);
+void glDisable(GLenum cap);
+void glDisableVertexAttribArray(GLuint index);
+void glDrawArrays(GLenum mode, GLint first, GLsizei count);
+void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
+void glEnable(GLenum cap);
+void glEnableVertexAttribArray(GLuint index);
+void glFinish(void);
+void glFlush(void);
+void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+void glFrontFace(GLenum mode);
+void glGenBuffers(GLsizei n, GLuint *buffers);
+void glGenerateMipmap(GLenum target);
+void glGenFramebuffers(GLsizei n, GLuint *framebuffers);
+void glGenRenderbuffers(GLsizei n, GLuint *renderbuffers);
+void glGenTextures(GLsizei n, GLuint *textures);
+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);
+void glGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GLint glGetAttribLocation(GLuint program, const GLchar *name);
+void glGetBooleanv(GLenum pname, GLboolean *data);
+void glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params);
+GLenum glGetError(void);
+void glGetFloatv(GLenum pname, GLfloat *data);
+void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params);
+void glGetIntegerv(GLenum pname, GLint *data);
+void glGetProgramiv(GLuint program, GLenum pname, GLint *params);
+void glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params);
+void glGetShaderiv(GLuint shader, GLenum pname, GLint *params);
+void glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+void glGetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+const GLubyte *glGetString(GLenum name);
+void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
+void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params);
+void glGetUniformfv(GLuint program, GLint location, GLfloat *params);
+void glGetUniformiv(GLuint program, GLint location, GLint *params);
+GLint glGetUniformLocation(GLuint program, const GLchar *name);
+void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
+void glGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
+void glGetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer);
+void glHint(GLenum target, GLenum mode);
+GLboolean glIsBuffer(GLuint buffer);
+GLboolean glIsEnabled(GLenum cap);
+GLboolean glIsFramebuffer(GLuint framebuffer);
+GLboolean glIsProgram(GLuint program);
+GLboolean glIsRenderbuffer(GLuint renderbuffer);
+GLboolean glIsShader(GLuint shader);
+GLboolean glIsTexture(GLuint texture);
+void glLineWidth(GLfloat width);
 void glLinkProgram(GLuint program);
+void glPixelStorei(GLenum pname, GLint param);
+void glPolygonOffset(GLfloat factor, GLfloat units);
+void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+void glReleaseShaderCompiler(void);
+void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+void glSampleCoverage(GLfloat value, GLboolean invert);
+void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
+void glShaderBinary(GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+void glShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+void glStencilFunc(GLenum func, GLint ref, GLuint mask);
+void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+void glStencilMask(GLuint mask);
+void glStencilMaskSeparate(GLenum face, GLuint mask);
+void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);
+void glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+void glTexParameterf(GLenum target, GLenum pname, GLfloat param);
+void glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params);
+void glTexParameteri(GLenum target, GLenum pname, GLint param);
+void glTexParameteriv(GLenum target, GLenum pname, const GLint *params);
+void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+void glUniform1f(GLint location, GLfloat v0);
+void glUniform1fv(GLint location, GLsizei count, const GLfloat *value);
+void glUniform1i(GLint location, GLint v0);
+void glUniform1iv(GLint location, GLsizei count, const GLint *value);
+void glUniform2f(GLint location, GLfloat v0, GLfloat v1);
+void glUniform2fv(GLint location, GLsizei count, const GLfloat *value);
+void glUniform2i(GLint location, GLint v0, GLint v1);
+void glUniform2iv(GLint location, GLsizei count, const GLint *value);
+void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+void glUniform3fv(GLint location, GLsizei count, const GLfloat *value);
+void glUniform3i(GLint location, GLint v0, GLint v1, GLint v2);
+void glUniform3iv(GLint location, GLsizei count, const GLint *value);
+void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+void glUniform4fv(GLint location, GLsizei count, const GLfloat *value);
+void glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+void glUniform4iv(GLint location, GLsizei count, const GLint *value);
+void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glUseProgram(GLuint program);
 void glValidateProgram(GLuint program);
-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);
-void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
-int  glGetAttribLocation(GLuint program, const GLchar* name);
-void glGetProgramiv(GLuint program, GLenum pname, GLint* params);
-void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
-void glGetShaderiv(GLuint shader, GLenum pname, GLint* params);
-void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
-void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
-void glGetUniformfv(GLuint program, GLint location, GLfloat* params);
-void glGetUniformiv(GLuint program, GLint location, GLint* params);
-int  glGetUniformLocation(GLuint program, const GLchar* name);
-void glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
-
-# The following are not used by GLDispatch but by GLESv2Dispatch
-void glBindFramebuffer(GLenum target, GLuint framebuffer);
-void glGenFramebuffers(GLsizei n, GLuint* framebuffers);
-void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLenum glCheckFramebufferStatus(GLenum target);
-GLboolean glIsFramebuffer(GLuint framebuffer);
-void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
-
-GLboolean glIsRenderbuffer(GLuint renderbuffer);
-void glBindRenderbuffer(GLenum target, GLuint renderbuffer);
-void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers);
-void glGenRenderbuffers(GLsizei n, GLuint *renderbuffers);
-void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params);
-void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-
-void glGenerateMipmap(GLenum target);
+void glVertexAttrib1f(GLuint index, GLfloat x);
+void glVertexAttrib1fv(GLuint index, const GLfloat *v);
+void glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
+void glVertexAttrib2fv(GLuint index, const GLfloat *v);
+void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+void glVertexAttrib3fv(GLuint index, const GLfloat *v);
+void glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void glVertexAttrib4fv(GLuint index, const GLfloat *v);
+void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/gles2_extensions.entries b/host/libs/virglrenderer/OpenGLESDispatch/gles2_extensions.entries
index 99abf3c..1453e87 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/gles2_extensions.entries
+++ b/host/libs/virglrenderer/OpenGLESDispatch/gles2_extensions.entries
@@ -1,7 +1,20 @@
 !gles2_extensions
 
-# GLES 2.0 extensions
-void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
-void glReleaseShaderCompiler(void);
-void glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
-void glVertexAttribPointerWithDataSize(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr, GLsizei dataSize);
+%#include <GLES2/gl2ext.h>
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
+
+void glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+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);
+void glCopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void glCompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+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);
+void glFramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+
+void glDrawBuffersEXT(GLsizei n, const GLenum *bufs);
+
+void glDrawArraysInstancedEXT(GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+void glDrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+
+void glVertexAttribDivisorEXT(GLuint index, GLuint divisor);
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/gles31_only.entries b/host/libs/virglrenderer/OpenGLESDispatch/gles31_only.entries
index d6062f2..53cc1e1 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/gles31_only.entries
+++ b/host/libs/virglrenderer/OpenGLESDispatch/gles31_only.entries
@@ -1,51 +1,38 @@
 !gles31_only
 
-# GLES 3.1 functions required by the translator library.
-
-%#include <GLES/gl.h>
-%#include <GLES3/gl3.h>
 %#include <GLES3/gl31.h>
 
-## New gets
-void glGetBooleani_v(GLenum target, GLuint index, GLboolean * data);
-
-## Memory barriers
-void glMemoryBarrier(GLbitfield barriers);
-void glMemoryBarrierByRegion(GLbitfield barriers);
-
-## Program pipelines
-void glGenProgramPipelines(GLsizei n, GLuint *pipelines);
-void glDeleteProgramPipelines(GLsizei n, const GLuint *pipelines);
-void glBindProgramPipeline(GLuint pipeline);
-
-void glGetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params);
-void glGetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
-
-void glValidateProgramPipeline(GLuint pipeline);
-GLboolean glIsProgramPipeline(GLuint pipeline);
+void glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+void glDispatchComputeIndirect(GLintptr indirect);
+void glDrawArraysIndirect(GLenum mode, const void *indirect);
+void glDrawElementsIndirect(GLenum mode, GLenum type, const void *indirect);
+void glFramebufferParameteri(GLenum target, GLenum pname, GLint param);
+void glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params);
+void glGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GLuint glGetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name);
+void glGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+void glGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GLint glGetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar *name);
 void glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program);
-
-## Separable shader programs
 void glActiveShaderProgram(GLuint pipeline, GLuint program);
-
-GLuint glCreateShaderProgramv(GLenum type, GLsizei count, const char **strings);
-
-void glProgramUniform1f(GLuint program, GLint location, GLfloat v0);
-void glProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1);
-void glProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
-void glProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLuint glCreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const*strings);
+void glBindProgramPipeline(GLuint pipeline);
+void glDeleteProgramPipelines(GLsizei n, const GLuint *pipelines);
+void glGenProgramPipelines(GLsizei n, GLuint *pipelines);
+GLboolean glIsProgramPipeline(GLuint pipeline);
+void glGetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params);
 void glProgramUniform1i(GLuint program, GLint location, GLint v0);
 void glProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1);
 void glProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
 void glProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
 void glProgramUniform1ui(GLuint program, GLint location, GLuint v0);
-void glProgramUniform2ui(GLuint program, GLint location, GLint v0, GLuint v1);
-void glProgramUniform3ui(GLuint program, GLint location, GLint v0, GLint v1, GLuint v2);
-void glProgramUniform4ui(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3);
-void glProgramUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
-void glProgramUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
-void glProgramUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
-void glProgramUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
+void glProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1);
+void glProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+void glProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void glProgramUniform1f(GLuint program, GLint location, GLfloat v0);
+void glProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1);
+void glProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+void glProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
 void glProgramUniform1iv(GLuint program, GLint location, GLsizei count, const GLint *value);
 void glProgramUniform2iv(GLuint program, GLint location, GLsizei count, const GLint *value);
 void glProgramUniform3iv(GLuint program, GLint location, GLsizei count, const GLint *value);
@@ -54,6 +41,10 @@
 void glProgramUniform2uiv(GLuint program, GLint location, GLsizei count, const GLuint *value);
 void glProgramUniform3uiv(GLuint program, GLint location, GLsizei count, const GLuint *value);
 void glProgramUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint *value);
+void glProgramUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
+void glProgramUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
+void glProgramUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
+void glProgramUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
 void glProgramUniformMatrix2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glProgramUniformMatrix3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
@@ -63,40 +54,19 @@
 void glProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-
-void glGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint * params);
-void glGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params);
-
-GLuint glGetProgramResourceIndex(GLuint program, GLenum programInterface, const char * name);
-GLint glGetProgramResourceLocation(GLuint program, GLenum programInterface, const char * name);
-void glGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, char * name);
-
-## Compute shaders
+void glValidateProgramPipeline(GLuint pipeline);
+void glGetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
 void glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
-void glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
-void glDispatchComputeIndirect(GLintptr indirect);
-
-## Separate vertex format / buffer binding
-void glBindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride);
-void glVertexAttribBinding(GLuint attribindex, GLuint bindingindex);
+void glGetBooleani_v(GLenum target, GLuint index, GLboolean *data);
+void glMemoryBarrier(GLbitfield barriers);
+void glMemoryBarrierByRegion(GLbitfield barriers);
+void glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+void glGetMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
+void glSampleMaski(GLuint maskNumber, GLbitfield mask);
+void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
+void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params);
+void glBindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
 void glVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
 void glVertexAttribIFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+void glVertexAttribBinding(GLuint attribindex, GLuint bindingindex);
 void glVertexBindingDivisor(GLuint bindingindex, GLuint divisor);
-
-## Indirect draws
-void glDrawArraysIndirect(GLenum mode, const void *indirect);
-void glDrawElementsIndirect(GLenum mode, GLenum type, const void *indirect);
-
-## Multisampling
-void glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
-void glSampleMaski(GLuint maskNumber, GLbitfield mask);
-void glGetMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
-
-## New framebuffer parameters
-void glFramebufferParameteri(GLenum target, GLenum pname, GLint param);
-void glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint * params);
-
-## Texture LOD queries
-# Already used in Translator's validations.
-# void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat * params);
-# void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint * params);
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/gles31_only_functions.h b/host/libs/virglrenderer/OpenGLESDispatch/gles31_only_functions.h
deleted file mode 100644
index a89faf7..0000000
--- a/host/libs/virglrenderer/OpenGLESDispatch/gles31_only_functions.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Auto-generated with: android/scripts/gen-entries.py --mode=funcargs android/android-emugl/host/libs/libOpenGLESDispatch/gles31_only.entries --output=android/android-emugl/host/include/OpenGLESDispatch/gles31_only_functions.h
-// DO NOT EDIT THIS FILE
-
-#ifndef GLES31_ONLY_FUNCTIONS_H
-#define GLES31_ONLY_FUNCTIONS_H
-
-#include <GLES/gl.h>
-#include <GLES3/gl3.h>
-#include <GLES3/gl31.h>
-#define LIST_GLES31_ONLY_FUNCTIONS(X) \
-  X(void, glGetBooleani_v, (GLenum target, GLuint index, GLboolean * data), (target, index, data)) \
-  X(void, glMemoryBarrier, (GLbitfield barriers), (barriers)) \
-  X(void, glMemoryBarrierByRegion, (GLbitfield barriers), (barriers)) \
-  X(void, glGenProgramPipelines, (GLsizei n, GLuint * pipelines), (n, pipelines)) \
-  X(void, glDeleteProgramPipelines, (GLsizei n, const GLuint * pipelines), (n, pipelines)) \
-  X(void, glBindProgramPipeline, (GLuint pipeline), (pipeline)) \
-  X(void, glGetProgramPipelineiv, (GLuint pipeline, GLenum pname, GLint * params), (pipeline, pname, params)) \
-  X(void, glGetProgramPipelineInfoLog, (GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog), (pipeline, bufSize, length, infoLog)) \
-  X(void, glValidateProgramPipeline, (GLuint pipeline), (pipeline)) \
-  X(GLboolean, glIsProgramPipeline, (GLuint pipeline), (pipeline)) \
-  X(void, glUseProgramStages, (GLuint pipeline, GLbitfield stages, GLuint program), (pipeline, stages, program)) \
-  X(GLuint, glCreateShaderProgramv, (GLenum type, GLsizei count, const char ** strings), (type, count, strings)) \
-  X(void, glProgramUniform1f, (GLuint program, GLint location, GLfloat v0), (program, location, v0)) \
-  X(void, glProgramUniform2f, (GLuint program, GLint location, GLfloat v0, GLfloat v1), (program, location, v0, v1)) \
-  X(void, glProgramUniform3f, (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2), (program, location, v0, v1, v2)) \
-  X(void, glProgramUniform4f, (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3), (program, location, v0, v1, v2, v3)) \
-  X(void, glProgramUniform1i, (GLuint program, GLint location, GLint v0), (program, location, v0)) \
-  X(void, glProgramUniform2i, (GLuint program, GLint location, GLint v0, GLint v1), (program, location, v0, v1)) \
-  X(void, glProgramUniform3i, (GLuint program, GLint location, GLint v0, GLint v1, GLint v2), (program, location, v0, v1, v2)) \
-  X(void, glProgramUniform4i, (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3), (program, location, v0, v1, v2, v3)) \
-  X(void, glProgramUniform1ui, (GLuint program, GLint location, GLuint v0), (program, location, v0)) \
-  X(void, glProgramUniform2ui, (GLuint program, GLint location, GLint v0, GLuint v1), (program, location, v0, v1)) \
-  X(void, glProgramUniform3ui, (GLuint program, GLint location, GLint v0, GLint v1, GLuint v2), (program, location, v0, v1, v2)) \
-  X(void, glProgramUniform4ui, (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLuint v3), (program, location, v0, v1, v2, v3)) \
-  X(void, glProgramUniform1fv, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value)) \
-  X(void, glProgramUniform2fv, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value)) \
-  X(void, glProgramUniform3fv, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value)) \
-  X(void, glProgramUniform4fv, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value)) \
-  X(void, glProgramUniform1iv, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value)) \
-  X(void, glProgramUniform2iv, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value)) \
-  X(void, glProgramUniform3iv, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value)) \
-  X(void, glProgramUniform4iv, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value)) \
-  X(void, glProgramUniform1uiv, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value)) \
-  X(void, glProgramUniform2uiv, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value)) \
-  X(void, glProgramUniform3uiv, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value)) \
-  X(void, glProgramUniform4uiv, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value)) \
-  X(void, glProgramUniformMatrix2fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glProgramUniformMatrix3fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glProgramUniformMatrix4fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glProgramUniformMatrix2x3fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glProgramUniformMatrix3x2fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glProgramUniformMatrix2x4fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glProgramUniformMatrix4x2fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glProgramUniformMatrix3x4fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glProgramUniformMatrix4x3fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value)) \
-  X(void, glGetProgramInterfaceiv, (GLuint program, GLenum programInterface, GLenum pname, GLint * params), (program, programInterface, pname, params)) \
-  X(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)) \
-  X(GLuint, glGetProgramResourceIndex, (GLuint program, GLenum programInterface, const char * name), (program, programInterface, name)) \
-  X(GLint, glGetProgramResourceLocation, (GLuint program, GLenum programInterface, const char * name), (program, programInterface, name)) \
-  X(void, glGetProgramResourceName, (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, char * name), (program, programInterface, index, bufSize, length, name)) \
-  X(void, glBindImageTexture, (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format), (unit, texture, level, layered, layer, access, format)) \
-  X(void, glDispatchCompute, (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z), (num_groups_x, num_groups_y, num_groups_z)) \
-  X(void, glDispatchComputeIndirect, (GLintptr indirect), (indirect)) \
-  X(void, glBindVertexBuffer, (GLuint bindingindex, GLuint buffer, GLintptr offset, GLintptr stride), (bindingindex, buffer, offset, stride)) \
-  X(void, glVertexAttribBinding, (GLuint attribindex, GLuint bindingindex), (attribindex, bindingindex)) \
-  X(void, glVertexAttribFormat, (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset), (attribindex, size, type, normalized, relativeoffset)) \
-  X(void, glVertexAttribIFormat, (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset), (attribindex, size, type, relativeoffset)) \
-  X(void, glVertexBindingDivisor, (GLuint bindingindex, GLuint divisor), (bindingindex, divisor)) \
-  X(void, glDrawArraysIndirect, (GLenum mode, const void * indirect), (mode, indirect)) \
-  X(void, glDrawElementsIndirect, (GLenum mode, GLenum type, const void * indirect), (mode, type, indirect)) \
-  X(void, glTexStorage2DMultisample, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations), (target, samples, internalformat, width, height, fixedsamplelocations)) \
-  X(void, glSampleMaski, (GLuint maskNumber, GLbitfield mask), (maskNumber, mask)) \
-  X(void, glGetMultisamplefv, (GLenum pname, GLuint index, GLfloat * val), (pname, index, val)) \
-  X(void, glFramebufferParameteri, (GLenum target, GLenum pname, GLint param), (target, pname, param)) \
-  X(void, glGetFramebufferParameteriv, (GLenum target, GLenum pname, GLint * params), (target, pname, params)) \
-
-
-#endif  // GLES31_ONLY_FUNCTIONS_H
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/gles3_only.entries b/host/libs/virglrenderer/OpenGLESDispatch/gles3_only.entries
index 89103fe..9742d38 100644
--- a/host/libs/virglrenderer/OpenGLESDispatch/gles3_only.entries
+++ b/host/libs/virglrenderer/OpenGLESDispatch/gles3_only.entries
@@ -1,149 +1,111 @@
 !gles3_only
 
-# GLES 3.0 functions required by the translator library.
+%#include <GLES3/gl31.h>
 
-%#include <GLES/gl.h>
-%#include <GLES3/gl3.h>
-%#include <GLES3/gl3ext.h>
+%// Return types must be single words, see GLDispatch.cpp
+%typedef const GLubyte* GL3constubyteptr;
 
-# glGetStringi
-GLconstubyteptr glGetStringi(GLenum name, GLint index);
-
-# VAOs
-void glGenVertexArrays(GLsizei n, GLuint* arrays);
-void glBindVertexArray(GLuint array);
-void glDeleteVertexArrays(GLsizei n, const GLuint *arrays);
-GLboolean glIsVertexArray(GLuint array);
-
-# Buffers
-void *glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+void glReadBuffer(GLenum src);
+void glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+void glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+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);
+void glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+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);
+void glGenQueries(GLsizei n, GLuint *ids);
+void glDeleteQueries(GLsizei n, const GLuint *ids);
+GLboolean glIsQuery(GLuint id);
+void glBeginQuery(GLenum target, GLuint id);
+void glEndQuery(GLenum target);
+void glGetQueryiv(GLenum target, GLenum pname, GLint *params);
+void glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
 GLboolean glUnmapBuffer(GLenum target);
-void glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
-
-void glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
-void glBindBufferBase(GLenum target, GLuint index, GLuint buffer);
-
-void glCopyBufferSubData(GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);
-
-void glClearBufferiv(GLenum buffer, GLint drawBuffer, const GLint * value);
-void glClearBufferuiv(GLenum buffer, GLint drawBuffer, const GLuint * value);
-void glClearBufferfv(GLenum buffer, GLint drawBuffer, const GLfloat * value);
-void glClearBufferfi(GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil);
-
-void glGetBufferParameteri64v(GLenum target, GLenum value, GLint64 * data);
-void glGetBufferPointerv(GLenum target, GLenum pname, GLvoid ** params);
-
-# UBOs
-void glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
-
-GLuint glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName);
-void glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar **uniformNames, GLuint *uniformIndices);
-
-void glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
-void glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
-
-# More uniform setters
-void glUniform1ui(GLint location, GLuint v0);
-void glUniform2ui(GLint location, GLuint v0, GLuint v1);
-void glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
-void glUniform4ui(GLint location, GLint v0, GLuint v1, GLuint v2, GLuint v3);
-void glUniform1uiv(GLint location, GLsizei count, const GLuint *value);
-void glUniform2uiv(GLint location, GLsizei count, const GLuint *value);
-void glUniform3uiv(GLint location, GLsizei count, const GLuint *value);
-void glUniform4uiv(GLint location, GLsizei count, const GLuint *value);
+void glGetBufferPointerv(GLenum target, GLenum pname, void **params);
+void glDrawBuffers(GLsizei n, const GLenum *bufs);
 void glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 void glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-
-void glGetUniformuiv(GLuint program, GLint location, GLuint *params);
-void glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
-
-# More vertex attribute setters / queries
-void glVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
-void glVertexAttribI4ui(GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
-void glVertexAttribI4iv(GLuint index, const GLint *v);
-void glVertexAttribI4uiv(GLuint index, const GLuint *v);
-void glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer);
-void glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
-void glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params);
-
-# Instanced draws
-void glVertexAttribDivisor(GLuint index, GLuint divisor);
-void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-void glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
-
-# Draw with known index range
-void glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices);
-
-# Sync
-GLsync glFenceSync(GLenum condition, GLbitfield flags);
-GLenum glClientWaitSync(GLsync wait_on, GLbitfield flags, GLuint64 timeout);
-void glWaitSync(GLsync wait_on, GLbitfield flags, GLuint64 timeout);
-void glDeleteSync(GLsync to_delete);
-GLboolean glIsSync(GLsync sync);
-void glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
-
-# MRT / MSAA render buffer
-void glDrawBuffers(GLsizei n, const GLenum *bufs);
-void glReadBuffer(GLenum src);
 void glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-void glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments);
-void glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+void glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 void glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
-void glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
-void glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-
-# Transform feedback
+void* glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+void glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
+void glBindVertexArray(GLuint array);
+void glDeleteVertexArrays(GLsizei n, const GLuint *arrays);
+void glGenVertexArrays(GLsizei n, GLuint *arrays);
+GLboolean glIsVertexArray(GLuint array);
+void glGetIntegeri_v(GLenum target, GLuint index, GLint *data);
 void glBeginTransformFeedback(GLenum primitiveMode);
 void glEndTransformFeedback(void);
-void glGenTransformFeedbacks(GLsizei n, GLuint *ids);
-void glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids);
+void glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+void glBindBufferBase(GLenum target, GLuint index, GLuint buffer);
+void glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+void glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+void glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+void glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
+void glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params);
+void glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
+void glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+void glVertexAttribI4iv(GLuint index, const GLint *v);
+void glVertexAttribI4uiv(GLuint index, const GLuint *v);
+void glGetUniformuiv(GLuint program, GLint location, GLuint *params);
+GLint glGetFragDataLocation(GLuint program, const GLchar *name);
+void glUniform1ui(GLint location, GLuint v0);
+void glUniform2ui(GLint location, GLuint v0, GLuint v1);
+void glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
+void glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void glUniform1uiv(GLint location, GLsizei count, const GLuint *value);
+void glUniform2uiv(GLint location, GLsizei count, const GLuint *value);
+void glUniform3uiv(GLint location, GLsizei count, const GLuint *value);
+void glUniform4uiv(GLint location, GLsizei count, const GLuint *value);
+void glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value);
+void glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value);
+void glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value);
+void glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL3constubyteptr glGetStringi(GLenum name, GLuint index);
+void glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+void glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+void glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GLuint glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName);
+void glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+void glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+void glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+void glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GLsync glFenceSync(GLenum condition, GLbitfield flags);
+GLboolean glIsSync(GLsync sync);
+void glDeleteSync(GLsync sync);
+GLenum glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+void glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+void glGetInteger64v(GLenum pname, GLint64 *data);
+void glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+void glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+void glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params);
+void glGenSamplers(GLsizei count, GLuint *samplers);
+void glDeleteSamplers(GLsizei count, const GLuint *samplers);
+GLboolean glIsSampler(GLuint sampler);
+void glBindSampler(GLuint unit, GLuint sampler);
+void glSamplerParameteri(GLuint sampler, GLenum pname, GLint param);
+void glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param);
+void glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
+void glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param);
+void glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params);
+void glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params);
+void glVertexAttribDivisor(GLuint index, GLuint divisor);
 void glBindTransformFeedback(GLenum target, GLuint id);
+void glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids);
+void glGenTransformFeedbacks(GLsizei n, GLuint *ids);
+GLboolean glIsTransformFeedback(GLuint id);
 void glPauseTransformFeedback(void);
 void glResumeTransformFeedback(void);
-GLboolean glIsTransformFeedback(GLuint id);
-void glTransformFeedbackVaryings(GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode);
-void glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, char * name);
-
-# Sampler objects
-void glGenSamplers(GLsizei n, GLuint *samplers);
-void glDeleteSamplers(GLsizei n, const GLuint * samplers);
-void glBindSampler(GLuint unit, GLuint sampler);
-void glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
-void glSamplerParameteri(GLuint sampler, GLenum pname, GLint param);
-void glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat * params);
-void glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint * params);
-void glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat * params);
-void glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint * params);
-GLboolean glIsSampler(GLuint sampler);
-
-# Query objects
-void glGenQueries(GLsizei n, GLuint * queries);
-void glDeleteQueries(GLsizei n, const GLuint * queries);
-void glBeginQuery(GLenum target, GLuint query);
-void glEndQuery(GLenum target);
-void glGetQueryiv(GLenum target, GLenum pname, GLint * params);
-void glGetQueryObjectuiv(GLuint query, GLenum pname, GLuint * params);
-GLboolean glIsQuery(GLuint query);
-
-# Shader binary objects
-void glProgramParameteri(GLuint program, GLenum pname, GLint value);
+void glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
 void glProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
-void glGetProgramBinary(GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary);
-
-# New glGets
-GLint glGetFragDataLocation(GLuint program, const char * name);
-void glGetInteger64v(GLenum pname, GLint64 * data);
-void glGetIntegeri_v(GLenum target, GLuint index, GLint * data);
-void glGetInteger64i_v(GLenum target, GLuint index, GLint64 * data);
-
-# Array/3D textures
-void glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * data);
+void glProgramParameteri(GLuint program, GLenum pname, GLint value);
+void glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments);
+void glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+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 glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * data);
-void glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data);
-void glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data);
-void glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
diff --git a/host/libs/virglrenderer/OpenGLESDispatch/gles_functions.h b/host/libs/virglrenderer/OpenGLESDispatch/gles_functions.h
new file mode 100644
index 0000000..d45dda3
--- /dev/null
+++ b/host/libs/virglrenderer/OpenGLESDispatch/gles_functions.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include "OpenGLESDispatch/gles1_core_functions.h"
+#include "OpenGLESDispatch/gles1_extensions_functions.h"
+#include "OpenGLESDispatch/gles2_core_functions.h"
+#include "OpenGLESDispatch/gles2_extensions_functions.h"
+#include "OpenGLESDispatch/gles3_only_functions.h"
+#include "OpenGLESDispatch/gles31_only_functions.h"
+
+#define LIST_GLES1_FUNCTIONS(X, Y) \
+    LIST_GLES1_CORE_FUNCTIONS(X) \
+    LIST_GLES1_EXTENSIONS_FUNCTIONS(Y) \
+
+#define LIST_GLES3_FUNCTIONS(X, Y) \
+    LIST_GLES2_CORE_FUNCTIONS(X) \
+    LIST_GLES2_EXTENSIONS_FUNCTIONS(Y) \
+    LIST_GLES3_ONLY_FUNCTIONS(X) \
+    LIST_GLES31_ONLY_FUNCTIONS(X)
diff --git a/host/libs/virglrenderer/OpenglRender/IOStream.h b/host/libs/virglrenderer/OpenglRender/IOStream.h
index ab561ec..82e5bde 100644
--- a/host/libs/virglrenderer/OpenglRender/IOStream.h
+++ b/host/libs/virglrenderer/OpenglRender/IOStream.h
@@ -1,105 +1,63 @@
 /*
-* 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.
-*/
+ * Copyright (C) 2018 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.
+ */
+
 #pragma once
 
-#include "ErrorLog.h"
-#include "android/base/files/Stream.h"
-
-#include <assert.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
 
 class IOStream {
-protected:
-    explicit IOStream(size_t bufSize) : m_bufsize(bufSize) {}
-
-    ~IOStream() {
-        // NOTE: m_buf was owned by the child class thus we expect it to be
-        // released before the object destruction.
-    }
-
-public:
-    size_t read(void* buf, size_t bufLen) {
-        if (!readRaw(buf, &bufLen)) {
-            return 0;
-        }
-        return bufLen;
+  public:
+    IOStream(unsigned char* buf, size_t bufSize) : m_buf(buf), m_bufSize(bufSize) {
     }
 
     unsigned char* alloc(size_t len) {
-        if (m_buf && len > m_free) {
-            if (flush() < 0) {
-                ERR("Failed to flush in alloc\n");
-                return NULL; // we failed to flush so something is wrong
-            }
+        if (m_allocSize + len > m_bufSize) {
+            printf("Command response is too large.\n");
+            return nullptr;
         }
-
-        if (!m_buf || len > m_bufsize) {
-            int allocLen = m_bufsize < len ? len : m_bufsize;
-            m_buf = (unsigned char *)allocBuffer(allocLen);
-            if (!m_buf) {
-                ERR("Alloc (%u bytes) failed\n", allocLen);
-                return NULL;
-            }
-            m_bufsize = m_free = allocLen;
-        }
-
-        unsigned char* ptr = m_buf + (m_bufsize - m_free);
-        m_free -= len;
-
-        return ptr;
+        unsigned char* buf = m_buf + m_allocSize;
+        m_allocSize += len;
+        return buf;
     }
 
     int flush() {
-        if (!m_buf || m_free == m_bufsize) return 0;
-
-        int stat = commitBuffer(m_bufsize - m_free);
-        m_buf = NULL;
-        m_free = 0;
-        return stat;
+        m_flushSize = m_allocSize;
+        return 0;
     }
 
-    void save(android::base::Stream* stream) {
-        stream->putBe32(m_bufsize);
-        stream->putBe32(m_free);
-        stream->putByte(m_buf != nullptr);
-        onSave(stream);
+    void* getDmaForReading(uint64_t guest_paddr) {
+        // GLDMA is not supported, so we don't have to implement this. Just keep
+        // a stub here to keep the generated decoder stubs happy
+        return nullptr;
     }
 
-    void load(android::base::Stream* stream) {
-        m_bufsize = stream->getBe32();
-        m_free = stream->getBe32();
-        const bool haveBuf = stream->getByte();
-        const auto buf = onLoad(stream);
-        m_buf = haveBuf ? buf : nullptr;
+    void unlockDma(uint64_t guest_paddr) {
+        // GLDMA is not supported, so we don't have to implement this. Just keep
+        // a stub here to keep the generated decoder stubs happy
     }
 
-    virtual void* getDmaForReading(uint64_t guest_paddr) = 0;
-    virtual void unlockDma(uint64_t guest_paddr) = 0;
+    size_t getFlushSize() {
+        return m_flushSize;
+    }
 
-protected:
-    virtual void *allocBuffer(size_t minSize) = 0;
-    virtual int commitBuffer(size_t size) = 0;
-    virtual const unsigned char *readRaw(void *buf, size_t *inout_len) = 0;
-    virtual void onSave(android::base::Stream* stream) = 0;
-    virtual unsigned char* onLoad(android::base::Stream* stream) = 0;
-
-private:
-    unsigned char* m_buf = nullptr;
-    size_t m_bufsize;
-    size_t m_free = 0;
+  private:
+    size_t m_allocSize = 0U;
+    size_t m_flushSize = 0U;
+    unsigned char* m_buf;
+    size_t m_bufSize;
 };
diff --git a/host/libs/virglrenderer/ProtocolUtils.h b/host/libs/virglrenderer/ProtocolUtils.h
index 7c323c9..fd0bebe 100644
--- a/host/libs/virglrenderer/ProtocolUtils.h
+++ b/host/libs/virglrenderer/ProtocolUtils.h
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
 #pragma once
 
 #include <assert.h>
diff --git a/host/libs/virglrenderer/README.md b/host/libs/virglrenderer/README.md
new file mode 100644
index 0000000..e9b1378
--- /dev/null
+++ b/host/libs/virglrenderer/README.md
@@ -0,0 +1,112 @@
+# AVDVirglRenderer
+
+This project implements an alternative for 'virglrenderer', a part of the
+Virgil 3D GPU project that normally implements the translation from the
+virtio-gpu-3d command stream & tgsi/gallium shaders, to desktop OpenGL.
+
+This version of the library keeps translation to a minimum and only works with
+a true EGL/GLES driver implementation on the host. It won't intercept and
+translate shaders, and no part of the GL state machine is processed in the
+emulated guest.
+
+The wire protocol used between the virtio-gpu DRM driver and QEMU's
+virtio-gpu-3d device is the same as that used by goldfish (the classic Android
+emulator). Submits (writes) are made with an `DRM_VIRTGPU_EXECBUFFER` call; the
+response comes back through a separate memory mapped buffer. Responses are very
+expensive and are minimized where possible, as they involve a pipeline flush and
+roundtrip to the host.
+
+## Structure
+
+### [`AVDVirglRenderer`](AVDVirglRenderer.cpp)[](#AVDVirglRenderer)
+
+Provides the entrypoints expected by QEMU for its libvirglrenderer integration.
+
+This is where contexts, resources and fences are monitored.
+
+### [`RenderControl`](RenderControl.cpp) [`Header`](RenderControl.h) [`Decoder`](renderControl_dec)[](#RenderControl)
+
+The RenderControl is analogous to EGL on the guest side. It has a similar API to
+EGL, except that not every EGL function can be implemented as one API call, and
+instead multiple RenderControl calls are made. The RenderControl architecture
+was precipitated by goldfish's requirement that EGL window surfaces and images
+would be directly mapped to GL texture names, but in AVDVirglRenderer we
+preserve them as EGL objects on the host side.
+
+This component contains a decoder for the wire protocol, and stubs for any
+functions that we do not need to implement. The wire protocol is completely
+unmodified.
+
+### [`GLESv1`](GLESv1.cpp) [`Header`](GLESv1.h) [`Decoder`](GLESv1_dec)[](#GLESv1)
+
+This component contains a decoder for the wire protocol, and stubs for any
+functions that we do not need to implement. Only the GL ES 1.1 extensions
+implemented by SwiftShader are implemented, and only if they are needed by
+Android. Any extensions provided by the wire protocol that are not supported by
+either are intentionally stubbed.
+
+### [`GLESv3`](GLESv3.cpp) [`Header`](GLESv3.h) [`Decoder`](GLESv3_dec)[](#GLESv3)
+
+This component contains a decoder for the wire protocol, and stubs for any
+functions that we do not need to implement. Only the core GL ES 3.0 API is
+implemented; no ES 2.0 extensions are supported, unless they are remappable to
+GL ES 3.0 features. GL ES 3.1 is not currently supported. Any extensions
+provided by the wire protocol that are not supported by either Android or
+SwiftShader are intentionally stubbed.
+
+Note that we are *not* stubbing ES 3.1 functions; these will crash if called.
+
+### [`ChecksumCalculator`](OpenglRenderer/ChecksumCalculator.cpp)[`Header`](ChecksumCalculator.h)[](#ChecksumCalculator)
+
+This code was taken from the Android emulator. The header has been slightly
+trimmed but its functionality has not been changed.
+
+### [`ChecksumCalculatorThreadInfo`](ChecksumCalculatorThreadInfo.h)[](#ChecksumCalculatorThreadInfo)
+
+This header has been added for compatibility with the decoder code generated by
+the `emugen_cuttlefish` tool. Unlike the original implementation, it is not
+thread safe. We do not require thread safety because no decoder state is shared
+between threads in AVDVirglRenderer without its own locking.
+
+### [`Context`](Context.h)[](#Context)
+
+The Context structure represents a virglrenderer context assigned by QEMU. Each
+time the driver's device node is opened by the guest, a new context is created.
+In the design of AVDVirglRenderer, there are two kinds of context. The first
+kind of context is for `gralloc`, and there is one of these contexts per guest
+process. The second kind of context is per-thread, used by the EGL/GLES
+implementation. This second kind of context can receive 3D commands, which are
+processed in their own thread by AVDVirglRenderer so as to minimize the number
+of synthetic calls we have to make (such as eglMakeCurrent()).
+
+### [`Resource`](Resource.h)[](#Resource)
+
+The Resource structure represents a virglrenderer resource assigned by QEMU.
+Each time the driver allocates memory through the device driver's interface, a
+new resource is created. Resources can be owned by the kernel (for example, the
+primary framebuffer surfaces), Gralloc (EGL window surfaces or images), or used
+for other purposes such as the Context response buffer and fencing.
+
+### [`EglConfig`](EglConfig.h)[](EglConfig)
+
+The EglConfig structure maintains a list of available EGLConfigs.
+
+### [`EglContext`](EglContext.h)[](EglContext)
+
+The EglContext structure maintains a list of active EGLContexts, and decides
+when they can be disposed of.
+
+### [`EglImage`](EglImage.h)[](EglImage)
+
+The EglImage structure maintains a list of active EGLImageKHRs, and decides
+when they can be disposed of.
+
+### [`EglSurface`](EglSurface.h)[](EglSurface)
+
+The EglSurface structure maintains a list of active EGLSurfaces, and decides
+when they can be disposed of.
+
+### [`EglSync`](EglSync.h)[](EglSync)
+
+The EglSync structure maintains a list of active EGLSyncKHRs, and decides
+when they can be disposed of.
diff --git a/host/libs/virglrenderer/RenderControl.cpp b/host/libs/virglrenderer/RenderControl.cpp
new file mode 100644
index 0000000..fd84eb5
--- /dev/null
+++ b/host/libs/virglrenderer/RenderControl.cpp
@@ -0,0 +1,868 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+#undef NDEBUG
+
+#include "Context.h"
+#include "EglConfig.h"
+#include "EglContext.h"
+#include "EglImage.h"
+#include "EglSurface.h"
+#include "EglSync.h"
+
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#include <unistd.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <OpenGLESDispatch/EGLDispatch.h>
+#include <OpenGLESDispatch/GLESv1Dispatch.h>
+#include <OpenGLESDispatch/GLESv3Dispatch.h>
+
+#include "virgl_hw.h"
+
+#include "RenderControl.h"
+
+#include <hardware/gralloc.h>
+#include <hardware/gralloc1.h>
+#include <nativebase/nativebase.h>
+#include <system/window.h>
+
+static void incRefANWB(android_native_base_t* base) {
+    ANativeWindowBuffer* anwb = reinterpret_cast<ANativeWindowBuffer*>(base);
+    anwb->layerCount++;
+}
+
+static void decRefANWB(android_native_base_t* base) {
+    ANativeWindowBuffer* anwb = reinterpret_cast<ANativeWindowBuffer*>(base);
+    if (anwb->layerCount > 0) {
+        anwb->layerCount--;
+        if (anwb->layerCount == 0)
+            delete anwb;
+    }
+}
+struct FakeANativeWindowBuffer : public ANativeWindowBuffer {
+    FakeANativeWindowBuffer() {
+        ANativeWindowBuffer();
+
+        common.incRef = incRefANWB;
+        common.decRef = decRefANWB;
+        layerCount = 0U;
+    }
+};
+
+static void incRefANW(android_native_base_t* base) {
+    ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(base);
+    anw->oem[0]++;
+}
+
+static void decRefANW(android_native_base_t* base) {
+    ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(base);
+    if (anw->oem[0] > 0) {
+        anw->oem[0]--;
+        if (anw->oem[0] == 0)
+            delete anw;
+    }
+}
+
+static int setSwapInterval(ANativeWindow*, int) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static int dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer) {
+    if (!window->oem[1])
+        return -EINVAL;
+    *buffer = reinterpret_cast<ANativeWindowBuffer*>(window->oem[1]);
+    window->oem[1] = 0;
+    return 0;
+}
+
+static int lockBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static int queueBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static int query(const ANativeWindow* window, int what, int* value) {
+    switch (what) {
+        case NATIVE_WINDOW_WIDTH:
+            return static_cast<int>(window->oem[2]);
+        case NATIVE_WINDOW_HEIGHT:
+            return static_cast<int>(window->oem[3]);
+        default:
+            return -EINVAL;
+    }
+}
+
+static int perform(ANativeWindow*, int, ...) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static int cancelBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) {
+    *fenceFd = -1;
+    return dequeueBuffer_DEPRECATED(window, buffer);
+}
+
+static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
+    if (fenceFd >= 0)
+        close(fenceFd);
+    return queueBuffer_DEPRECATED(window, buffer);
+}
+
+static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
+    if (fenceFd >= 0)
+        close(fenceFd);
+    return cancelBuffer_DEPRECATED(window, buffer);
+}
+
+struct FakeANativeWindow : public ANativeWindow {
+    FakeANativeWindow(uint32_t width, uint32_t height) {
+        ANativeWindow();
+
+        common.incRef = incRefANW;
+        common.decRef = decRefANW;
+        oem[0] = 0;
+        oem[2] = static_cast<intptr_t>(width);
+        oem[3] = static_cast<intptr_t>(height);
+
+        this->setSwapInterval = ::setSwapInterval;
+        this->dequeueBuffer_DEPRECATED = ::dequeueBuffer_DEPRECATED;
+        this->lockBuffer_DEPRECATED = ::lockBuffer_DEPRECATED;
+        this->queueBuffer_DEPRECATED = ::queueBuffer_DEPRECATED;
+        this->query = ::query;
+        this->perform = ::perform;
+        this->cancelBuffer_DEPRECATED = ::cancelBuffer_DEPRECATED;
+        this->dequeueBuffer = ::dequeueBuffer;
+        this->queueBuffer = ::queueBuffer;
+        this->cancelBuffer = ::cancelBuffer;
+    }
+};
+
+// Helpers
+
+static ANativeWindowBuffer* resourceToANWB(Resource* res) {
+    ANativeWindowBuffer* buffer = new (std::nothrow) FakeANativeWindowBuffer();
+    if (!buffer)
+        return nullptr;
+
+    buffer->width = res->args.width;
+    buffer->height = res->args.height;
+    buffer->stride = res->args.width;
+    buffer->handle = reinterpret_cast<const native_handle_t*>(res->args.handle);
+    buffer->usage_deprecated = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+                               GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER;
+    buffer->usage =
+        GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN | GRALLOC1_CONSUMER_USAGE_CPU_WRITE_OFTEN |
+        GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE | GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN |
+        GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN | GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
+
+    switch (res->args.format) {
+        case VIRGL_FORMAT_B8G8R8A8_UNORM:
+            buffer->format = HAL_PIXEL_FORMAT_BGRA_8888;
+            break;
+        case VIRGL_FORMAT_B5G6R5_UNORM:
+            buffer->format = HAL_PIXEL_FORMAT_RGB_565;
+            break;
+        case VIRGL_FORMAT_R8G8B8A8_UNORM:
+            buffer->format = HAL_PIXEL_FORMAT_RGBA_8888;
+            break;
+        case VIRGL_FORMAT_R8G8B8X8_UNORM:
+            buffer->format = HAL_PIXEL_FORMAT_RGBX_8888;
+            break;
+        default:
+            delete buffer;
+            return nullptr;
+    }
+
+    return buffer;
+}
+
+// RenderControl
+
+static GLint rcGetRendererVersion() {
+    return 1;  // seems to be hard-coded
+}
+
+static EGLint rcGetEGLVersion(void* ctx_, EGLint* major, EGLint* minor) {
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    return s_egl.eglInitialize(rc->dpy, major, minor);
+}
+
+static EGLint rcQueryEGLString(void* ctx_, EGLenum name, void* buffer, EGLint bufferSize) {
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    const char* str = s_egl.eglQueryString(rc->dpy, name);
+    if (!str)
+        str = "";
+
+    if (strlen(str) > (size_t)bufferSize) {
+        memset(buffer, 0, bufferSize);
+        return -strlen(str);
+    }
+
+    char* strOut = static_cast<char*>(buffer);
+    strncpy(strOut, str, bufferSize - 1);
+    strOut[bufferSize - 1] = 0;
+
+    return strlen(strOut) + 1U;
+}
+
+static std::string replaceESVersionString(const std::string& prev, const char* const newver) {
+    // Do not touch ES 1.x contexts (they will all be 1.1 anyway)
+    if (prev.find("ES-CM") != std::string::npos)
+        return prev;
+
+    size_t esStart = prev.find("ES ");
+    size_t esEnd = prev.find(" ", esStart + 3);
+
+    // Do not change out-of-spec version strings.
+    if (esStart == std::string::npos || esEnd == std::string::npos)
+        return prev;
+
+    std::string res = prev.substr(0, esStart + 3);
+    res += newver;
+    res += prev.substr(esEnd);
+    return res;
+}
+
+static EGLint rcGetGLString(void* ctx_, EGLenum name, void* buffer, EGLint bufferSize) {
+    std::string glStr;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    if (rc->ctx->ctx) {
+        const char* str = nullptr;
+        switch (rc->ctx->ctx->api) {
+            case EglContext::GLESApi::GLESApi_CM:
+                str = reinterpret_cast<const char*>(s_gles1.glGetString(name));
+                break;
+            default:
+                str = reinterpret_cast<const char*>(s_gles3.glGetString(name));
+                break;
+        }
+        if (str)
+            glStr += str;
+    }
+
+    // FIXME: Should probably filter the extensions list like the emulator
+    //        does. We need to handle ES2 on ES3 compatibility for older
+    //        Android versions, as well as filter out unsupported features.
+
+    if (name == GL_EXTENSIONS) {
+        glStr += ChecksumCalculator::getMaxVersionStr();
+        glStr += " ";
+
+        // FIXME: Hard-coded to 3.0 for now. We should attempt to detect 3.1.
+        glStr += "ANDROID_EMU_gles_max_version_3_0";
+        glStr += " ";
+    }
+
+    // FIXME: Add support for async swap and the fence_sync extensions
+
+    // We don't support GLDMA; use VIRTGPU_RESOURCE_CREATE and a combination of
+    // VIRTGPU_TRANSFER_TO_HOST and VIRTGPU_TRANSFER_FROM_HOST.
+
+    // FIXME: Add support for 'no host error'
+
+    if (name == GL_VERSION)
+        glStr = replaceESVersionString(glStr, "3.0");
+
+    int nextBufferSize = glStr.size() + 1;
+
+    if (!buffer || nextBufferSize > bufferSize)
+        return -nextBufferSize;
+
+    snprintf((char*)buffer, nextBufferSize, "%s", glStr.c_str());
+    return nextBufferSize;
+}
+
+static EGLint rcGetNumConfigs(uint32_t* numAttribs) {
+    *numAttribs = EglConfig::kNumAttribs;
+    return EglConfig::vec.size();
+}
+
+static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer) {
+    size_t configAttribBytes = sizeof(EglConfig::kAttribs);
+    size_t nConfigs = EglConfig::vec.size();
+    size_t sizeNeeded = configAttribBytes + nConfigs * configAttribBytes;
+
+    if (bufSize < sizeNeeded)
+        return -sizeNeeded;
+
+    memcpy(buffer, &EglConfig::kAttribs, configAttribBytes);
+    size_t offset = EglConfig::kNumAttribs;
+    for (auto const& config : EglConfig::vec) {
+        memcpy(&buffer[offset], config->attribs, configAttribBytes);
+        offset += EglConfig::kNumAttribs;
+    }
+
+    return nConfigs;
+}
+
+static EGLint rcChooseConfig(void* ctx_, EGLint* attribs, uint32_t, uint32_t* config_ints,
+                             uint32_t configs_size) {
+    EGLint num_config;
+    EGLConfig configs[configs_size];
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    EGLBoolean ret = s_egl.eglChooseConfig(rc->dpy, attribs, configs, configs_size, &num_config);
+    if (!ret)
+        num_config = 0;
+
+    if (configs_size) {
+        for (EGLint i = 0; i < num_config; i++) {
+            config_ints[i] = ~0U;
+            EGLint config_id;
+            if (s_egl.eglGetConfigAttrib(rc->dpy, configs[i], EGL_CONFIG_ID, &config_id)) {
+                for (size_t i = 0; i < EglConfig::vec.size(); i++) {
+                    if (EglConfig::vec[i]->attribs[4] == config_id)
+                        config_ints[i] = i;
+                }
+            }
+            if (config_ints[i] == ~0U) {
+                num_config = 0;
+                break;
+            }
+        }
+        if (!num_config)
+            memset(config_ints, 0, configs_size * sizeof(uint32_t));
+    }
+
+    return num_config;
+}
+
+static EGLint rcGetFBParam(EGLint) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static uint32_t rcCreateContext(void* ctx_, uint32_t config_, uint32_t share_, uint32_t glVersion) {
+    // clang-format off
+    EGLint attrib_list[] = {
+        EGL_CONTEXT_CLIENT_VERSION,    0,
+        EGL_CONTEXT_MINOR_VERSION_KHR, 0,
+        EGL_NONE
+    };
+    // clang-format on
+    switch (glVersion) {
+        case EglContext::GLESApi::GLESApi_CM:
+            attrib_list[1] = 1;
+            attrib_list[3] = 1;
+            break;
+        case EglContext::GLESApi::GLESApi_2:
+            attrib_list[1] = 2;
+            break;
+        case EglContext::GLESApi::GLESApi_3_0:
+            attrib_list[1] = 3;
+            break;
+        case EglContext::GLESApi::GLESApi_3_1:
+            attrib_list[1] = 3;
+            attrib_list[3] = 1;
+            break;
+    }
+    if (!attrib_list[1])
+        return 0U;
+
+    if (config_ > EglConfig::vec.size())
+        return 0U;
+    EglConfig const* config = EglConfig::vec[config_];
+
+    EGLContext share_context = EGL_NO_CONTEXT;
+    if (share_ > 0) {
+        std::map<uint32_t, EglContext*>::iterator context_it;
+        context_it = EglContext::map.find(share_);
+        if (context_it == EglContext::map.end())
+            return 0U;
+
+        EglContext const* share = context_it->second;
+        share_context = share->context;
+    }
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    EGLContext context_ =
+        s_egl.eglCreateContext(rc->dpy, config->config, share_context, attrib_list);
+    if (context_ == EGL_NO_CONTEXT)
+        return 0U;
+
+    EglContext* context = new (std::nothrow)
+        EglContext(context_, rc->ctx->handle, (enum EglContext::GLESApi)glVersion);
+    if (!context) {
+        s_egl.eglDestroyContext(rc->dpy, context_);
+        return 0U;
+    }
+
+    return context->id;
+}
+
+static void rcDestroyContext(void* ctx_, uint32_t ctx) {
+    std::map<uint32_t, EglContext*>::iterator it;
+    it = EglContext::map.find(ctx);
+    if (it == EglContext::map.end())
+        return;
+
+    EglContext* context = it->second;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    s_egl.eglDestroyContext(rc->dpy, context->context);
+    context->context = EGL_NO_CONTEXT;
+    if (context->disposable())
+        delete context;
+}
+
+static uint32_t rcCreateWindowSurface(void* ctx_, uint32_t config_, uint32_t width,
+                                      uint32_t height) {
+    if (config_ > EglConfig::vec.size())
+        return 0U;
+
+    EglConfig const* config = EglConfig::vec[config_];
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    EglSurface* surface =
+        new (std::nothrow) EglSurface(config->config, rc->ctx->handle, width, height);
+    if (!surface)
+        return 0U;
+
+    return surface->id;
+}
+
+static void rcDestroyWindowSurface(void* ctx_, uint32_t surface_) {
+    std::map<uint32_t, EglSurface*>::iterator it;
+    it = EglSurface::map.find(surface_);
+    if (it == EglSurface::map.end())
+        return;
+
+    EglSurface* surface = it->second;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    s_egl.eglDestroySurface(rc->dpy, surface->surface);
+    surface->surface = EGL_NO_SURFACE;
+    if (surface->disposable()) {
+        delete surface->window;
+        delete surface;
+    }
+}
+
+static uint32_t rcCreateColorBuffer(uint32_t, uint32_t, GLenum) {
+    // NOTE: This CreateColorBuffer implementation is a no-op which returns a
+    //       special surface ID to indicate that a pbuffer surface should be
+    //       created. This is necessary because the emulator does not create a
+    //       true pbuffer, it always creates a fake one. We don't want this.
+    return ~1U;
+}
+
+static void rcOpenColorBuffer(uint32_t) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void rcCloseColorBuffer(uint32_t) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void rcSetWindowColorBuffer(void* ctx_, uint32_t windowSurface, uint32_t colorBuffer) {
+    std::map<uint32_t, EglSurface*>::iterator surface_it;
+    surface_it = EglSurface::map.find(windowSurface);
+    if (surface_it == EglSurface::map.end())
+        return;
+
+    EglSurface* surface = surface_it->second;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+
+    if (colorBuffer == ~1U) {
+        EGLint const attrib_list[] = { EGL_WIDTH, (EGLint)surface->width, EGL_HEIGHT,
+                                       (EGLint)surface->height, EGL_NONE };
+        assert(surface->surface == EGL_NO_SURFACE && "Pbuffer set twice");
+        surface->surface = s_egl.eglCreatePbufferSurface(rc->dpy, surface->config, attrib_list);
+    } else {
+        std::map<uint32_t, Resource*>::iterator resource_it;
+        resource_it = Resource::map.find(colorBuffer);
+        if (resource_it == Resource::map.end())
+            return;
+
+        Resource* res = resource_it->second;
+        ANativeWindowBuffer* buffer = resourceToANWB(res);
+        if (!buffer)
+            return;
+
+        if (surface->surface == EGL_NO_SURFACE) {
+            surface->window =
+                new (std::nothrow) FakeANativeWindow(res->args.width, res->args.height);
+            if (!surface->window)
+                return;
+
+            NativeWindowType native_window = reinterpret_cast<NativeWindowType>(surface->window);
+            surface->window->oem[1] = (intptr_t)buffer;
+            surface->surface =
+                s_egl.eglCreateWindowSurface(rc->dpy, surface->config, native_window, nullptr);
+        } else {
+            surface->window->oem[1] = (intptr_t)buffer;
+            s_egl.eglSwapBuffers(rc->dpy, surface->surface);
+        }
+    }
+}
+
+static int rcFlushWindowColorBuffer(uint32_t windowSurface) {
+    std::map<uint32_t, EglSurface*>::iterator it;
+    it = EglSurface::map.find(windowSurface);
+    return it == EglSurface::map.end() ? -1 : 0;
+}
+
+static EGLint rcMakeCurrent(void* ctx_, uint32_t context_, uint32_t drawSurf, uint32_t readSurf) {
+    std::map<uint32_t, EglContext*>::iterator context_it;
+    context_it = EglContext::map.find(context_);
+    if (context_it == EglContext::map.end())
+        return EGL_FALSE;
+
+    EglContext* context = context_it->second;
+
+    std::map<uint32_t, EglSurface*>::iterator surface_it;
+    surface_it = EglSurface::map.find(drawSurf);
+    if (surface_it == EglSurface::map.end())
+        return EGL_FALSE;
+
+    EglSurface* draw_surface = surface_it->second;
+
+    surface_it = EglSurface::map.find(readSurf);
+    if (surface_it == EglSurface::map.end())
+        return EGL_FALSE;
+
+    EglSurface* read_surface = surface_it->second;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+
+    EglSurface* old_draw_surface = draw_surface->bind(rc->ctx->handle, false);
+    if (old_draw_surface)
+        old_draw_surface->unbind(false);
+
+    EglSurface* old_read_surface = read_surface->bind(rc->ctx->handle, true);
+    if (old_read_surface)
+        old_read_surface->unbind(true);
+
+    EglContext* old_context = context->bind(rc->ctx->handle);
+    if (old_context)
+        old_context->unbind();
+
+    EGLBoolean ret = s_egl.eglMakeCurrent(rc->dpy, draw_surface->surface, read_surface->surface,
+                                          context->context);
+    if (!ret) {
+        // If eglMakeCurrent fails, it's specified *not* to have unbound the
+        // previous contexts or surfaces, but many implementations do. This bug
+        // isn't worked around here, and we just assume the implementations obey
+        // the spec.
+        context->unbind();
+        if (old_context)
+            old_context->bind(rc->ctx->handle);
+        read_surface->unbind(true);
+        if (old_read_surface)
+            old_read_surface->bind(rc->ctx->handle, true);
+        draw_surface->unbind(false);
+        if (old_draw_surface)
+            old_draw_surface->bind(rc->ctx->handle, false);
+    } else {
+        if (old_context && old_context->disposable())
+            delete old_context;
+        if (old_read_surface && old_read_surface->disposable())
+            delete old_read_surface;
+        if (old_draw_surface && old_draw_surface->disposable())
+            delete old_draw_surface;
+        rc->ctx->unbind();
+        rc->ctx->bind(context);
+    }
+
+    return (EGLint)ret;
+}
+
+static void rcFBPost(uint32_t) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static void rcFBSetSwapInterval(void* ctx_, EGLint interval) {
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    s_egl.eglSwapInterval(rc->dpy, interval);
+}
+
+static void rcBindTexture(void* ctx_, uint32_t colorBuffer) {
+    std::map<uint32_t, Resource*>::iterator it;
+    it = Resource::map.find(colorBuffer);
+    if (it == Resource::map.end())
+        return;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    Resource* res = it->second;
+    if (!res->image) {
+        ANativeWindowBuffer* buffer = resourceToANWB(res);
+        if (!buffer)
+            return;
+
+        EGLClientBuffer client_buffer = static_cast<EGLClientBuffer>(buffer);
+        EGLImageKHR image = s_egl.eglCreateImageKHR(
+            rc->dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, client_buffer, nullptr);
+        if (image == EGL_NO_IMAGE_KHR)
+            return;
+
+        EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
+        if (!img) {
+            s_egl.eglDestroyImageKHR(rc->dpy, image);
+            return;
+        }
+
+        // FIXME: House keeping, because we won't get asked to delete the image
+        //        object otherwise, so we need to keep a reference to it..
+        res->image = img;
+    }
+
+    if (rc->ctx->ctx->api == EglContext::GLESApi::GLESApi_CM) {
+        // FIXME: Unconditional use of GL_TEXTURE_2D here is wrong
+        s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, res->image->image);
+    } else {
+        // FIXME: Unconditional use of GL_TEXTURE_2D here is wrong
+        s_gles3.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, res->image->image);
+    }
+}
+
+static void rcBindRenderbuffer(void* ctx_, uint32_t colorBuffer) {
+    std::map<uint32_t, Resource*>::iterator it;
+    it = Resource::map.find(colorBuffer);
+    if (it == Resource::map.end())
+        return;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    Resource* res = it->second;
+    if (!res->image) {
+        ANativeWindowBuffer* buffer = resourceToANWB(res);
+        if (!buffer)
+            return;
+
+        EGLClientBuffer client_buffer = static_cast<EGLClientBuffer>(buffer);
+        EGLImageKHR image = s_egl.eglCreateImageKHR(
+            rc->dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, client_buffer, nullptr);
+        if (image == EGL_NO_IMAGE_KHR)
+            return;
+
+        EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
+        if (!img) {
+            s_egl.eglDestroyImageKHR(rc->dpy, image);
+            return;
+        }
+
+        // FIXME: House keeping, because we won't get asked to delete the image
+        //        object otherwise, so we need to keep a reference to it..
+        res->image = img;
+    }
+
+    if (rc->ctx->ctx->api == EglContext::GLESApi::GLESApi_CM) {
+        s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, res->image->image);
+    } else {
+        s_gles3.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, res->image->image);
+    }
+}
+
+static EGLint rcColorBufferCacheFlush(uint32_t, EGLint, int) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static void rcReadColorBuffer(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*) {
+    printf("%s: not implemented\n", __func__);
+}
+
+static int rcUpdateColorBuffer(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static int rcOpenColorBuffer2(uint32_t) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static uint32_t rcCreateClientImage(void* ctx_, uint32_t context_, EGLenum target, GLuint buffer_) {
+    std::map<uint32_t, EglContext*>::iterator it;
+    it = EglContext::map.find(context_);
+    if (it == EglContext::map.end())
+        return 0U;
+
+    EglContext* context = it->second;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(buffer_);
+    EGLImageKHR image = s_egl.eglCreateImageKHR(rc->dpy, context, target, buffer, nullptr);
+    EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
+    if (!img) {
+        s_egl.eglDestroyImageKHR(rc->dpy, image);
+        return 0U;
+    }
+
+    return img->id;
+}
+
+static int rcDestroyClientImage(uint32_t image_) {
+    std::map<uint32_t, EglImage*>::iterator it;
+    it = EglImage::map.find(image_);
+    if (it == EglImage::map.end())
+        return EGL_FALSE;
+
+    EglImage* image = it->second;
+
+    delete image;
+    return EGL_TRUE;
+}
+
+static void rcSelectChecksumHelper(void* ctx_, uint32_t protocol, uint32_t) {
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    rc->ctx->checksum_calc.setVersion(protocol);
+}
+
+static void rcCreateSyncKHR(void* ctx_, EGLenum type, EGLint* attribs, uint32_t, int,
+                            uint64_t* glsync_out, uint64_t* syncthread_out) {
+    *syncthread_out = 0ULL;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    EGLSyncKHR sync = s_egl.eglCreateSyncKHR(rc->dpy, type, attribs);
+    if (sync == EGL_NO_SYNC_KHR) {
+        *glsync_out = 0ULL;
+        return;
+    }
+
+    EglSync* syn = new (std::nothrow) EglSync(sync);
+    if (!syn) {
+        s_egl.eglDestroySyncKHR(rc->dpy, sync);
+        *glsync_out = 0ULL;
+        return;
+    }
+
+    *glsync_out = syn->id;
+}
+
+static EGLint rcClientWaitSyncKHR(void* ctx_, uint64_t sync_, EGLint flags, uint64_t timeout) {
+    std::map<uint64_t, EglSync*>::iterator it;
+    it = EglSync::map.find(sync_);
+    if (it == EglSync::map.end())
+        return EGL_CONDITION_SATISFIED_KHR;
+
+    EglSync* sync = it->second;
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    return s_egl.eglClientWaitSyncKHR(rc->dpy, sync->sync, flags, timeout);
+}
+
+static void rcFlushWindowColorBufferAsync(uint32_t windowSurface) {
+    // No-op
+}
+
+static int rcDestroySyncKHR(void* ctx_, uint64_t sync_) {
+    std::map<uint64_t, EglSync*>::iterator it;
+    it = EglSync::map.find(sync_);
+    if (it == EglSync::map.end())
+        return EGL_FALSE;
+
+    EglSync* sync = it->second;
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    return s_egl.eglDestroySyncKHR(rc->dpy, sync->sync);
+}
+
+static void rcSetPuid(void* ctx_, uint64_t proto) {
+    union {
+        uint64_t proto;
+        struct {
+            int pid;
+            int tid;
+        } id;
+    } puid;
+
+    puid.proto = proto;
+
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    rc->ctx->setPidTid(puid.id.pid, puid.id.tid);
+}
+
+static int rcUpdateColorBufferDMA(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*,
+                                  uint32_t) {
+    printf("%s: not implemented\n", __func__);
+    return 0;
+}
+
+static uint32_t rcCreateColorBufferDMA(uint32_t, uint32_t, GLenum, int) {
+    printf("%s: not implemented\n", __func__);
+    return 0U;
+}
+
+static void rcWaitSyncKHR(void* ctx_, uint64_t sync_, EGLint flags) {
+    std::map<uint64_t, EglSync*>::iterator it;
+    it = EglSync::map.find(sync_);
+    if (it == EglSync::map.end())
+        return;
+
+    EglSync* sync = it->second;
+    RenderControl* rc = static_cast<RenderControl*>(ctx_);
+    // FIXME: No eglWaitSyncKHR support in SwiftShader
+    //        This call will BLOCK when it should be asynchronous!
+    s_egl.eglClientWaitSyncKHR(rc->dpy, sync->sync, flags, EGL_FOREVER_KHR);
+}
+
+RenderControl::RenderControl(Context* ctx_, EGLDisplay dpy_) {
+    rcGetRendererVersion = ::rcGetRendererVersion;
+    rcGetEGLVersion_dec = ::rcGetEGLVersion;
+    rcQueryEGLString_dec = ::rcQueryEGLString;
+    rcGetGLString_dec = ::rcGetGLString;
+    rcGetNumConfigs = ::rcGetNumConfigs;
+    rcGetConfigs = ::rcGetConfigs;
+    rcChooseConfig_dec = ::rcChooseConfig;
+    rcGetFBParam = ::rcGetFBParam;
+    rcCreateContext_dec = ::rcCreateContext;
+    rcDestroyContext_dec = ::rcDestroyContext;
+    rcCreateWindowSurface_dec = ::rcCreateWindowSurface;
+    rcDestroyWindowSurface_dec = ::rcDestroyWindowSurface;
+    rcCreateColorBuffer = ::rcCreateColorBuffer;
+    rcOpenColorBuffer = ::rcOpenColorBuffer;
+    rcCloseColorBuffer = ::rcCloseColorBuffer;
+    rcSetWindowColorBuffer_dec = ::rcSetWindowColorBuffer;
+    rcFlushWindowColorBuffer = ::rcFlushWindowColorBuffer;
+    rcMakeCurrent_dec = ::rcMakeCurrent;
+    rcFBPost = ::rcFBPost;
+    rcFBSetSwapInterval_dec = ::rcFBSetSwapInterval;
+    rcBindTexture_dec = ::rcBindTexture;
+    rcBindRenderbuffer_dec = ::rcBindRenderbuffer;
+    rcColorBufferCacheFlush = ::rcColorBufferCacheFlush;
+    rcReadColorBuffer = ::rcReadColorBuffer;
+    rcUpdateColorBuffer = ::rcUpdateColorBuffer;
+    rcOpenColorBuffer2 = ::rcOpenColorBuffer2;
+    rcCreateClientImage_dec = ::rcCreateClientImage;
+    rcDestroyClientImage = ::rcDestroyClientImage;
+    rcSelectChecksumHelper_dec = ::rcSelectChecksumHelper;
+    rcCreateSyncKHR_dec = ::rcCreateSyncKHR;
+    rcClientWaitSyncKHR_dec = ::rcClientWaitSyncKHR;
+    rcFlushWindowColorBufferAsync = ::rcFlushWindowColorBufferAsync;
+    rcDestroySyncKHR_dec = ::rcDestroySyncKHR;
+    rcSetPuid_dec = ::rcSetPuid;
+    rcUpdateColorBufferDMA = ::rcUpdateColorBufferDMA;
+    rcCreateColorBufferDMA = ::rcCreateColorBufferDMA;
+    rcWaitSyncKHR_dec = ::rcWaitSyncKHR;
+
+    dpy = dpy_;
+    ctx = ctx_;
+}
diff --git a/host/libs/virglrenderer/RenderControl.h b/host/libs/virglrenderer/RenderControl.h
new file mode 100644
index 0000000..146adf4
--- /dev/null
+++ b/host/libs/virglrenderer/RenderControl.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include "renderControl_dec/renderControl_dec.h"
+
+typedef void* EGLDisplay;
+
+struct Context;
+
+struct RenderControl : public renderControl_decoder_context_t {
+    RenderControl(Context* ctx_, EGLDisplay dpy_);
+    EGLDisplay dpy;
+    Context* ctx;
+};
diff --git a/host/libs/virglrenderer/Resource.h b/host/libs/virglrenderer/Resource.h
new file mode 100644
index 0000000..eb12782
--- /dev/null
+++ b/host/libs/virglrenderer/Resource.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+extern "C" {
+#include <virgl/virglrenderer.h>
+}
+
+#include <cstdint>
+#include <cstdlib>
+#include <map>
+
+#include <GLES/gl.h>
+
+#include <sys/uio.h>
+
+#include "EglImage.h"
+
+struct Context;
+
+struct Resource {
+    static std::map<uint32_t, Resource*> map;
+
+    Resource(virgl_renderer_resource_create_args* args_, uint32_t num_iovs_, iovec* iov_)
+        : args(*args_), num_iovs(num_iovs_), tex_id(0U), iov(iov_) {
+        reallocLinear();
+        map.emplace(args.handle, this);
+    }
+
+    ~Resource() {
+        map.erase(args.handle);
+        delete image;
+    }
+
+    void reallocLinear() {
+        if (linearShadow && num_iovs <= 1)
+            free(linear);
+        linearShadow = num_iovs > 1 ? true : false;
+        if (linearShadow) {
+            uint32_t i;
+            for (i = 0, linearSize = 0U; i < num_iovs; i++)
+                linearSize += iov[i].iov_len;
+            linear = realloc(linear, linearSize);
+        } else if (num_iovs == 1) {
+            linearSize = iov[0].iov_len;
+            linear = iov[0].iov_base;
+        } else {
+            linearSize = 0U;
+            linear = nullptr;
+        }
+    }
+
+    std::map<uint32_t, Context*> context_map;
+    virgl_renderer_resource_create_args args;
+    EglImage* image = nullptr;
+    size_t linearSize = 0U;
+    void* linear = nullptr;
+    uint32_t num_iovs;
+    GLuint tex_id;
+    iovec* iov;
+
+  private:
+    bool linearShadow = false;
+};
diff --git a/host/libs/virglrenderer/emugl/common/logging.h b/host/libs/virglrenderer/emugl/common/logging.h
index e5c77ef..081df61 100644
--- a/host/libs/virglrenderer/emugl/common/logging.h
+++ b/host/libs/virglrenderer/emugl/common/logging.h
@@ -1,22 +1,22 @@
 /*
-* 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.
-*/
+ * Copyright (C) 2018 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.
+ */
 
 #pragma once
 
-#include "OpenglRender/render_api_types.h"
+typedef void (*emugl_logger_t)(const char* fmt, ...);
 
 extern emugl_logger_t emugl_logger;
 extern emugl_logger_t emugl_cxt_logger;
diff --git a/host/libs/virglrenderer/include/VirtioGpuCmd.h b/host/libs/virglrenderer/include/VirtioGpuCmd.h
new file mode 100644
index 0000000..6ffacd3
--- /dev/null
+++ b/host/libs/virglrenderer/include/VirtioGpuCmd.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+struct VirtioGpuCmd {
+    uint32_t op;
+    uint32_t cmdSize;
+    unsigned char buf[0];
+} __attribute__((packed));
diff --git a/host/libs/virglrenderer/include/android/api-level.h b/host/libs/virglrenderer/include/android/api-level.h
new file mode 100644
index 0000000..2d2f096
--- /dev/null
+++ b/host/libs/virglrenderer/include/android/api-level.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_API_LEVEL_H
+#define ANDROID_API_LEVEL_H
+
+/*
+ * Magic version number for a current development build, which has
+ * not yet turned into an official release.
+ */
+#define __ANDROID_API__ 10000
+
+#endif /* ANDROID_API_LEVEL_H */
diff --git a/host/libs/virglrenderer/include/android/sync.h b/host/libs/virglrenderer/include/android/sync.h
new file mode 100644
index 0000000..1ae728a
--- /dev/null
+++ b/host/libs/virglrenderer/include/android/sync.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+extern "C" {
+int sync_wait(int fd, int timeout);
+};
diff --git a/host/libs/virglrenderer/include/cutils/native_handle.h b/host/libs/virglrenderer/include/cutils/native_handle.h
new file mode 100644
index 0000000..b92a663
--- /dev/null
+++ b/host/libs/virglrenderer/include/cutils/native_handle.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+struct native_handle_t;
+
+typedef const struct native_handle_t* buffer_handle_t;
diff --git a/host/libs/virglrenderer/include/hardware/gralloc.h b/host/libs/virglrenderer/include/hardware/gralloc.h
new file mode 100644
index 0000000..8446ba4
--- /dev/null
+++ b/host/libs/virglrenderer/include/hardware/gralloc.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <cutils/native_handle.h>
+
+#include <hardware/hardware.h>
+
+struct android_ycbcr;
+
+enum {
+    GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003U,
+    GRALLOC_USAGE_SW_WRITE_OFTEN = 0x00000030U,
+    GRALLOC_USAGE_HW_TEXTURE = 0x00000100U,
+    GRALLOC_USAGE_HW_RENDER = 0x00000200U,
+};
+
+struct gralloc_module_t {
+    hw_module_t common;
+    int (*registerBuffer)(gralloc_module_t const*, buffer_handle_t);
+    int (*unregisterBuffer)(gralloc_module_t const*, buffer_handle_t);
+    int (*lock)(gralloc_module_t const*, buffer_handle_t, int, int, int, int, int, void**);
+    int (*unlock)(gralloc_module_t const*, buffer_handle_t);
+    int (*perform)(gralloc_module_t const*, int, ...);
+    int (*lock_ycbcr)(gralloc_module_t const*, buffer_handle_t, int, int, int, int, int,
+                      android_ycbcr*);
+    int (*lockAsync)(gralloc_module_t const*, buffer_handle_t, int, int, int, int, int, void**, int);
+    int (*unlockAsync)(gralloc_module_t const*, buffer_handle_t, int*);
+    int (*lockAsync_ycbcr)(gralloc_module_t const*, buffer_handle_t, int, int, int, int, int,
+                           android_ycbcr*, int);
+    void* reserved_proc[3];
+};
diff --git a/host/libs/virglrenderer/include/hardware/gralloc1.h b/host/libs/virglrenderer/include/hardware/gralloc1.h
new file mode 100644
index 0000000..b02decf
--- /dev/null
+++ b/host/libs/virglrenderer/include/hardware/gralloc1.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <hardware/hardware.h>
+
+#include <cutils/native_handle.h>
+
+#define GRALLOC_MODULE_API_VERSION_1_0 HARDWARE_MAKE_API_VERSION(1, 0)
+
+#define GRALLOC_HARDWARE_MODULE_ID "gralloc"
+
+enum {
+    GRALLOC1_ERROR_NONE = 0,
+    GRALLOC1_ERROR_BAD_HANDLE = 2,
+    GRALLOC1_ERROR_BAD_VALUE = 3,
+    GRALLOC1_ERROR_UNDEFINED = 6,
+};
+
+enum {
+    GRALLOC1_FUNCTION_LOCK = 18,
+    GRALLOC1_FUNCTION_UNLOCK = 20,
+};
+
+enum {
+    GRALLOC1_CONSUMER_USAGE_CPU_READ = 1ULL << 1,
+    GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN = 1ULL << 2 | GRALLOC1_CONSUMER_USAGE_CPU_READ,
+    GRALLOC1_CONSUMER_USAGE_CPU_WRITE = 1ULL << 5,
+    GRALLOC1_CONSUMER_USAGE_CPU_WRITE_OFTEN = 1ULL << 6 | GRALLOC1_CONSUMER_USAGE_CPU_WRITE,
+    GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE = 1ULL << 8,
+};
+
+enum {
+    GRALLOC1_PRODUCER_USAGE_CPU_READ = 1ULL << 1,
+    GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN = 1ULL << 2 | GRALLOC1_PRODUCER_USAGE_CPU_READ,
+    GRALLOC1_PRODUCER_USAGE_CPU_WRITE = 1ULL << 5,
+    GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN = 1ULL << 6 | GRALLOC1_PRODUCER_USAGE_CPU_WRITE,
+    GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET = 1ULL << 9,
+};
+
+typedef void (*gralloc1_function_pointer_t)();
+
+struct gralloc1_rect_t {
+    int32_t left;
+    int32_t top;
+    int32_t width;
+    int32_t height;
+};
+
+struct gralloc1_device_t {
+    hw_device_t common;
+    void (*getCapabilities)(gralloc1_device_t*, uint32_t*, int32_t*);
+    gralloc1_function_pointer_t (*getFunction)(gralloc1_device_t*, int32_t);
+};
+
+typedef int32_t (*GRALLOC1_PFN_LOCK)(gralloc1_device_t*, buffer_handle_t, uint64_t, uint64_t,
+                                     const gralloc1_rect_t*, void**, int32_t);
+typedef int32_t (*GRALLOC1_PFN_UNLOCK)(gralloc1_device_t*, buffer_handle_t, int32_t*);
+
+static inline int gralloc1_open(const hw_module_t* module, gralloc1_device_t** device) {
+    return module->methods->open(module, GRALLOC_HARDWARE_MODULE_ID,
+                                 reinterpret_cast<hw_device_t**>(device));
+}
diff --git a/host/libs/virglrenderer/include/hardware/hardware.h b/host/libs/virglrenderer/include/hardware/hardware.h
new file mode 100644
index 0000000..21d6dc4
--- /dev/null
+++ b/host/libs/virglrenderer/include/hardware/hardware.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#define MAKE_TAG_CONSTANT(A, B, C, D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))
+
+#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')
+#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')
+
+#define HARDWARE_MAKE_API_VERSION(maj, min) ((((maj)&0xff) << 8) | ((min)&0xff))
+
+#define HARDWARE_HAL_API_VERSION HARDWARE_MAKE_API_VERSION(1, 0)
+
+struct hw_module_methods_t;
+
+struct hw_module_t {
+    uint32_t tag;
+    uint16_t module_api_version;
+    uint16_t hal_api_version;
+    const char* id;
+    const char* name;
+    const char* author;
+    hw_module_methods_t* methods;
+    void* dso;
+#ifdef __LP64__
+    uint64_t reserved[32 - 7];
+#else
+    uint32_t reserved[32 - 7];
+#endif
+};
+
+struct hw_device_t {
+    uint32_t tag;
+    uint32_t version;
+    struct hw_module_t* module;
+#ifdef __LP64__
+    uint64_t reserved[12];
+#else
+    uint32_t reserved[12];
+#endif
+    int (*close)(hw_device_t* device);
+};
+
+struct hw_module_methods_t {
+    int (*open)(const hw_module_t*, const char*, hw_device_t**);
+};
+
+extern "C" {
+int hw_get_module(const char* id, const hw_module_t** module);
+};
diff --git a/host/libs/virglrenderer/include/nativebase/nativebase.h b/host/libs/virglrenderer/include/nativebase/nativebase.h
new file mode 100644
index 0000000..c2e84d7
--- /dev/null
+++ b/host/libs/virglrenderer/include/nativebase/nativebase.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <cutils/native_handle.h>
+
+#include <cstdint>
+#include <cstring>
+
+// clang-format off
+#define ANDROID_NATIVE_MAKE_CONSTANT(a, b, c, d) \
+    ((static_cast<unsigned int>(a) << 24) | \
+     (static_cast<unsigned int>(b) << 16) | \
+     (static_cast<unsigned int>(c) <<  8) | \
+     (static_cast<unsigned int>(d) <<  0))
+// clang-format on
+
+struct android_native_base_t {
+    int magic;
+    int version;
+    void* reserved[4];
+    void (*incRef)(android_native_base_t*);
+    void (*decRef)(android_native_base_t*);
+};
+
+#define ANDROID_NATIVE_BUFFER_MAGIC ANDROID_NATIVE_MAKE_CONSTANT('_', 'b', 'f', 'r')
+
+struct ANativeWindowBuffer {
+    ANativeWindowBuffer() {
+        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+        common.version = sizeof(ANativeWindowBuffer);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+
+    android_native_base_t common;
+
+    int width;
+    int height;
+    int stride;
+    int format;
+    int usage_deprecated;
+    uintptr_t layerCount;
+
+    void* reserved[1];
+
+    const native_handle_t* handle;
+    uint64_t usage;
+
+    void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
+};
diff --git a/host/libs/virglrenderer/include/sync/sync.h b/host/libs/virglrenderer/include/sync/sync.h
new file mode 100644
index 0000000..1ae728a
--- /dev/null
+++ b/host/libs/virglrenderer/include/sync/sync.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+extern "C" {
+int sync_wait(int fd, int timeout);
+};
diff --git a/host/libs/virglrenderer/include/system/graphics.h b/host/libs/virglrenderer/include/system/graphics.h
new file mode 100644
index 0000000..884db9c
--- /dev/null
+++ b/host/libs/virglrenderer/include/system/graphics.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+enum {
+    HAL_PIXEL_FORMAT_RGBA_8888 = 1,
+    HAL_PIXEL_FORMAT_RGBX_8888 = 2,
+    HAL_PIXEL_FORMAT_RGB_888 = 3,
+    HAL_PIXEL_FORMAT_RGB_565 = 4,
+    HAL_PIXEL_FORMAT_BGRA_8888 = 5,
+    HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 34,
+    HAL_PIXEL_FORMAT_YV12 = 842094169,
+};
diff --git a/host/libs/virglrenderer/include/system/window.h b/host/libs/virglrenderer/include/system/window.h
new file mode 100644
index 0000000..f986274
--- /dev/null
+++ b/host/libs/virglrenderer/include/system/window.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <nativebase/nativebase.h>
+#include <system/graphics.h>
+
+#define ANDROID_NATIVE_WINDOW_MAGIC ANDROID_NATIVE_MAKE_CONSTANT('_', 'w', 'n', 'd')
+
+enum {
+    NATIVE_WINDOW_WIDTH = 0,
+    NATIVE_WINDOW_HEIGHT = 1,
+};
+
+struct ANativeWindow {
+    ANativeWindow() : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0) {
+        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+        common.version = sizeof(ANativeWindowBuffer);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+
+    android_native_base_t common;
+
+    const uint32_t flags;
+    const int minSwapInterval;
+    const int maxSwapInterval;
+    const float xdpi;
+    const float ydpi;
+    intptr_t oem[4];
+
+    int (*setSwapInterval)(ANativeWindow*, int);
+    int (*dequeueBuffer_DEPRECATED)(ANativeWindow*, ANativeWindowBuffer**);
+    int (*lockBuffer_DEPRECATED)(ANativeWindow*, ANativeWindowBuffer*);
+    int (*queueBuffer_DEPRECATED)(ANativeWindow*, ANativeWindowBuffer*);
+    int (*query)(const ANativeWindow*, int, int*);
+    int (*perform)(ANativeWindow*, int, ...);
+    int (*cancelBuffer_DEPRECATED)(ANativeWindow*, ANativeWindowBuffer*);
+    int (*dequeueBuffer)(ANativeWindow*, ANativeWindowBuffer**, int*);
+    int (*queueBuffer)(ANativeWindow*, ANativeWindowBuffer*, int);
+    int (*cancelBuffer)(ANativeWindow*, ANativeWindowBuffer*, int);
+};
+
+static inline int native_window_set_usage(ANativeWindow*, uint64_t) {
+    // No-op
+    return 0;
+}
+
+static inline int native_window_dequeue_buffer_and_wait(ANativeWindow* anw,
+                                                        ANativeWindowBuffer** anwb) {
+    return anw->dequeueBuffer_DEPRECATED(anw, anwb);
+}
diff --git a/host/libs/virglrenderer/libvirglrenderer.lds b/host/libs/virglrenderer/libvirglrenderer.lds
new file mode 100644
index 0000000..9fc62d5
--- /dev/null
+++ b/host/libs/virglrenderer/libvirglrenderer.lds
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+{
+global:
+	# virglrenderer API
+	virgl_renderer_init;
+	virgl_renderer_poll;
+	virgl_renderer_get_cursor_data;
+	virgl_renderer_resource_create;
+	virgl_renderer_resource_unref;
+	virgl_renderer_context_create;
+	virgl_renderer_context_destroy;
+	virgl_renderer_submit_cmd;
+	virgl_renderer_transfer_read_iov;
+	virgl_renderer_transfer_write_iov;
+	virgl_renderer_get_cap_set;
+	virgl_renderer_fill_caps;
+	virgl_renderer_resource_attach_iov;
+	virgl_renderer_resource_detach_iov;
+	virgl_renderer_create_fence;
+	virgl_renderer_force_ctx_0;
+	virgl_renderer_ctx_attach_resource;
+	virgl_renderer_ctx_detach_resource;
+	virgl_renderer_resource_get_info;
+
+	# fake gralloc1 implementation
+	hw_get_module;
+
+	# fake libsync implementation
+	sync_wait;
+
+	# Type-strings and type-infos required by sanitizers
+	_ZTS*;
+	_ZTI*;
+
+local:
+	*;
+};
diff --git a/host/libs/virglrenderer/renderControl_dec/renderControl.attrib b/host/libs/virglrenderer/renderControl_dec/renderControl.attrib
index 7e06ce4..6ff20b6 100644
--- a/host/libs/virglrenderer/renderControl_dec/renderControl.attrib
+++ b/host/libs/virglrenderer/renderControl_dec/renderControl.attrib
@@ -1,21 +1,20 @@
-# For documentation on the .attrib file format, see:
-# android/android-emugl/host/tools/emugen/README
-
 GLOBAL
-	base_opcode 10000
-	encoder_headers <stdint.h> <EGL/egl.h> "glUtils.h"
+    base_opcode 10000
 
 rcGetEGLVersion
+    flag custom_decoder
     dir major out
     len major sizeof(EGLint)
     dir minor out
     len minor sizeof(EGLint)
 
 rcQueryEGLString
+    flag custom_decoder
     dir buffer out
     len buffer bufferSize
 
 rcGetGLString
+    flag custom_decoder
     dir buffer out
     len buffer bufferSize
 
@@ -28,34 +27,79 @@
     len buffer bufSize
 
 rcChooseConfig
+    flag custom_decoder
     dir attribs in
     len attribs attribs_size
     dir configs out
     var_flag configs nullAllowed
     len configs configs_size*sizeof(uint32_t)
 
+rcCreateContext
+    flag custom_decoder
+
+rcDestroyContext
+    flag custom_decoder
+
+rcCreateWindowSurface
+    flag custom_decoder
+
+rcDestroyWindowSurface
+    flag custom_decoder
+
+rcCloseColorBuffer
+    flag flushOnEncode
+
+rcSetWindowColorBuffer
+    flag custom_decoder
+
+rcMakeCurrent
+    flag custom_decoder
+
+rcFBSetSwapInterval
+    flag custom_decoder
+
+rcBindTexture
+    flag custom_decoder
+
+rcBindRenderbuffer
+    flag custom_decoder
+
 rcReadColorBuffer
     dir pixels out
-    len pixels (((glUtilsPixelBitSize(format, type) * width) >> 3) * height)
 
 rcUpdateColorBuffer
     dir pixels in
-    len pixels (((glUtilsPixelBitSize(format, type) * width) >> 3) * height)
     var_flag pixels isLarge
 
+rcCreateClientImage
+    flag custom_decoder
+
+rcSelectChecksumHelper
+    flag custom_decoder
+
+rcCreateSyncKHR
+    flag custom_decoder
+    dir attribs in
+    len attribs num_attribs
+    dir glsync_out out
+    len glsync_out sizeof(uint64_t)
+    dir syncthread_out out
+    len syncthread_out sizeof(uint64_t)
+
+rcClientWaitSyncKHR
+    flag custom_decoder
+
+rcDestroySyncKHR
+    flag custom_decoder
+
+rcSetPuid
+    flag custom_decoder
+
 rcUpdateColorBufferDMA
     dir pixels in
     len pixels pixels_size
     var_flag pixels DMA
     flag flushOnEncode
 
-rcCloseColorBuffer
-    flag flushOnEncode
-
-rcCreateSyncKHR
-    dir attribs in
-    len attribs num_attribs
-    dir glsync_out out
-    len glsync_out sizeof(uint64_t)
-    dir syncthread_out out
-    len syncthread_out sizeof(uint64_t)
+rcWaitSyncKHR
+    flag custom_decoder
diff --git a/host/libs/virglrenderer/renderControl_dec/renderControl.in b/host/libs/virglrenderer/renderControl_dec/renderControl.in
index 0cf77f6..e1dea92 100644
--- a/host/libs/virglrenderer/renderControl_dec/renderControl.in
+++ b/host/libs/virglrenderer/renderControl_dec/renderControl.in
@@ -20,7 +20,7 @@
 GL_ENTRY(void, rcFBSetSwapInterval, EGLint interval)
 GL_ENTRY(void, rcBindTexture, uint32_t colorBuffer)
 GL_ENTRY(void, rcBindRenderbuffer, uint32_t colorBuffer)
-GL_ENTRY(EGLint, rcColorBufferCacheFlush, uint32_t colorbuffer, EGLint postCount,int forRead)
+GL_ENTRY(EGLint, rcColorBufferCacheFlush, uint32_t colorbuffer, EGLint postCount, int forRead)
 GL_ENTRY(void, rcReadColorBuffer, uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void *pixels)
 GL_ENTRY(int, rcUpdateColorBuffer, uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void *pixels)
 GL_ENTRY(int, rcOpenColorBuffer2, uint32_t colorbuffer)
diff --git a/host/libs/virglrenderer/renderControl_dec/renderControl_types.h b/host/libs/virglrenderer/renderControl_dec/renderControl_types.h
new file mode 100644
index 0000000..dd6b412
--- /dev/null
+++ b/host/libs/virglrenderer/renderControl_dec/renderControl_types.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018 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.
+ */
+#pragma once
+
+#include <EGL/egl.h>
+
+#include <GLES/gl.h>