android: Add OpenGLES emulation support.

BEWARE: Not production quality. This is a working patch. The final
        version will probably be splitted into separate patches.
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index f97ecb6..8fcf46d 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -16,6 +16,8 @@
 
 obj-$(CONFIG_ANDROID_PIPE) += android_pipe.o
 obj-$(CONFIG_ANDROID_PIPE) += android_pipe_test.o
+obj-$(CONFIG_ANDROID_PIPE) += android_net_pipe.o
+obj-$(CONFIG_ANDROID_PIPE) += android_opengles.o
 obj-$(CONFIG_ANDROID_PIPE) += android_adb_dbg.o
 obj-$(CONFIG_ANDROID_PIPE) += android_adb.o
 
diff --git a/hw/misc/android_net_pipe.c b/hw/misc/android_net_pipe.c
new file mode 100644
index 0000000..90d1364
--- /dev/null
+++ b/hw/misc/android_net_pipe.c
@@ -0,0 +1,489 @@
+/* Copyright (C) 2014 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.
+**
+** Description
+**
+** Implementation of 'tcp' and 'unix' Android pipes. These can be used
+** to connect a guest process directly with a host TCP or Unix socket.
+**
+** For TCP, connections are limited to localhost (127.0.0.1) ports for
+** security reasons (doing otherwise might allow any application to
+** sneakily connect to the Internet when running under emulation).
+**
+** This is also used by the 'opengles' Android pipe service to send
+** wire protocol data to the GPU emulation libraries.
+*/
+
+#include "qemu/main-loop.h"
+#include "qemu/sockets.h"
+#include "hw/misc/android_pipe.h"
+#include "hw/misc/android_opengles.h"
+
+#include <errno.h>
+//#include <sys/select.h>
+
+/* Set to 1 or 2 for debug traces */
+#define DEBUG 1
+
+#if DEBUG >= 1
+#  define D(...)   printf(__VA_ARGS__), printf("\n")
+#else
+#  define D(...)   ((void)0)
+#endif
+
+#if DEBUG >= 2
+#  define DD(...)                       printf(__VA_ARGS__), printf("\n")
+#  define DDASSERT(cond)                _ANDROID_ASSERT(cond, "Assertion failure: ", #cond)
+#  define DDASSERT_INT_OP(cond,val,op)  _ANDROID_ASSERT_INT_OP(cond,val,op)
+#else
+#  define DD(...)                       ((void)0)
+#  define DDASSERT(cond)                ((void)0)
+#  define DDASSERT_INT_OP(cond,val,op)  ((void)0)
+#endif
+
+#define DDASSERT_INT_LT(cond,val)  DDASSERT_INT_OP(cond,val,<)
+#define DDASSERT_INT_LTE(cond,val)  DDASSERT_INT_OP(cond,val,<=)
+#define DDASSERT_INT_GT(cond,val)  DDASSERT_INT_OP(cond,val,>)
+#define DDASSERT_INT_GTE(cond,val)  DDASSERT_INT_OP(cond,val,>=)
+#define DDASSERT_INT_EQ(cond,val)  DDASSERT_INT_OP(cond,val,==)
+#define DDASSERT_INT_NEQ(cond,val)  DDASSERT_INT_OP(cond,val,!=)
+
+enum {
+    STATE_INIT,
+    STATE_CONNECTING,
+    STATE_CONNECTED,
+    STATE_CLOSING_GUEST,
+    STATE_CLOSING_SOCKET
+};
+
+typedef struct {
+    void *hwpipe;
+    int state;
+    int wakeWanted;
+    int wakeActual;
+    int fd;
+} NetPipe;
+
+/* Free a network pipe */
+static void net_pipe_free(NetPipe *pipe)
+{
+    /* Close the socket */
+    int fd = pipe->fd;
+    if (fd >= 0) {
+        qemu_set_fd_handler(fd, NULL, NULL, NULL);
+        closesocket(fd);
+        pipe->fd = -1;
+    }
+    g_free(pipe);
+}
+
+static void net_pipe_read_handler(void* opaque);
+static void net_pipe_write_handler(void* opaque);
+
+static void net_pipe_reset_state(NetPipe *pipe)
+{
+    IOHandler *read_handler = NULL;
+    IOHandler *write_handler = NULL;
+
+    if ((pipe->wakeWanted & PIPE_WAKE_WRITE) != 0) {
+        write_handler = net_pipe_write_handler;
+    }
+
+    if (pipe->state == STATE_CONNECTED &&
+        (pipe->wakeWanted & PIPE_WAKE_READ) != 0) {
+       read_handler = net_pipe_read_handler;
+    }
+    qemu_set_fd_handler(pipe->fd, read_handler, write_handler, pipe);
+}
+
+static void net_pipe_close_from_socket(void *opaque)
+{
+    NetPipe *pipe = opaque;
+
+    /* If the guest already ordered the pipe to be closed,
+     * delete immediately */
+    if (pipe->state == STATE_CLOSING_GUEST) {
+        net_pipe_free(pipe);
+        return;
+    }
+
+    /* Force the closure of the pipe channel - if a guest is blocked
+     * waiting for a wake signal, it will receive an error. */
+    if (pipe->hwpipe != NULL) {
+        android_pipe_close(pipe->hwpipe);
+        pipe->hwpipe = NULL;
+    }
+
+    pipe->state = STATE_CLOSING_SOCKET;
+    net_pipe_reset_state(pipe);
+}
+
+/* Called when data arrives on the pipe's socket. */
+static void net_pipe_read_handler(void* opaque)
+{
+    NetPipe *pipe = opaque;
+
+    pipe->wakeActual |= PIPE_WAKE_READ;
+    if ((pipe->wakeWanted & PIPE_WAKE_READ) != 0) {
+        android_pipe_wake(pipe->hwpipe, pipe->wakeActual);
+        pipe->wakeWanted &= ~PIPE_WAKE_READ;
+    }
+    net_pipe_reset_state(pipe);
+}
+
+/* Called when the pipe's file socket becomes writable. */
+static void net_pipe_write_handler(void* opaque)
+{
+    NetPipe *pipe = opaque;
+
+    pipe->wakeActual |= PIPE_WAKE_WRITE;
+    if ((pipe->wakeWanted & PIPE_WAKE_WRITE) != 0) {
+        android_pipe_wake(pipe->hwpipe, pipe->wakeActual);
+        pipe->wakeWanted &= ~PIPE_WAKE_WRITE;
+    }
+    net_pipe_reset_state(pipe);
+}
+
+static void net_pipe_close_from_guest(void *opaque)
+{
+    NetPipe *pipe = opaque;
+    net_pipe_free(pipe);
+}
+
+static int net_pipe_ready_send(NetPipe *pipe)
+{
+    if (pipe->state == STATE_CONNECTED) {
+        return 0;
+    } else if (pipe->state == STATE_CONNECTING) {
+        return PIPE_ERROR_AGAIN;
+    } else if (pipe->hwpipe == NULL) {
+        return PIPE_ERROR_INVAL;
+    } else {
+        return PIPE_ERROR_IO;
+    }
+}
+
+static int net_pipe_send_buffers(void* opaque,
+                                 const AndroidPipeBuffer *buffers,
+                                 int num_buffers)
+{
+    NetPipe *pipe = opaque;
+
+    int ret = net_pipe_ready_send(pipe);
+    if (ret != 0) {
+        return ret;
+    }
+
+    const AndroidPipeBuffer* buff = buffers;
+    const AndroidPipeBuffer* buff_end = buff + num_buffers;
+    int count = 0;
+    for (; buff < buff_end; ++buff) {
+        count += buff->size;
+    }
+
+    buff = buffers;
+
+    int buff_start = 0;
+    ret = 0;
+    while (count > 0) {
+        int avail = buff->size - buff_start;
+        ssize_t len = send(pipe->fd, (const void*)(buff->data + buff_start), avail, 0);
+
+        if (len > 0) {
+            /* the write succeeded */
+            buff_start += len;
+            if (buff_start >= buff->size) {
+                buff++;
+                buff_start = 0;
+            }
+            count -= (int)len;
+            ret += (int)len;
+            continue;
+        }
+        if (len == 0) {
+            /* reached the end of stream? */
+            if (ret == 0) {
+                ret = PIPE_ERROR_IO;
+            }
+            break;
+        }
+        if (ret > 0) {
+            break;
+        }
+        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+            ret = PIPE_ERROR_AGAIN;
+        } else {
+            ret = PIPE_ERROR_IO;
+        }
+        break;
+    }
+    return ret;
+}
+
+static int net_pipe_recv_buffers(void *opaque,
+                                 AndroidPipeBuffer *buffers,
+                                 int num_buffers)
+{
+    NetPipe *pipe = opaque;
+
+    AndroidPipeBuffer* buff = buffers;
+    AndroidPipeBuffer* buff_end = buff + num_buffers;
+
+    int count = 0;
+    for (; buff < buff_end; ++buff) {
+        count += buff->size;
+    }
+
+    buff = buffers;
+
+    int ret = 0;
+    int buff_start = 0;
+    while (count > 0) {
+        int avail = buff->size - buff_start;
+        ssize_t len = recv(pipe->fd, (void*)(buff->data + buff_start), avail, 0);
+
+        if (len > 0) {
+            /* the read succeeded. */
+            buff_start += len;
+            if (buff_start >= buff->size) {
+                buff++;
+                buff_start = 0;
+            }
+            count -= (int) len;
+            ret += (int) len;
+            continue;
+        }
+
+        if (len == 0) {
+            /* reached the end of stream? */
+            if (ret == 0)
+                ret = PIPE_ERROR_IO;
+            break;
+        }
+
+        if (ret > 0) {
+            /* if data was already read, just return it. */
+            break;
+        }
+
+        /* need to return an appropriate error code. */
+        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+            ret = PIPE_ERROR_AGAIN;
+        } else {
+            ret = PIPE_ERROR_IO;
+        }
+        break;
+    }
+    return ret;
+}
+
+static unsigned net_pipe_poll(void *opaque)
+{
+    NetPipe *pipe = opaque;
+#if 1
+    return pipe->wakeActual;
+#else
+    unsigned result = 0;
+
+    do {
+        fd_set read_fds, write_fds;
+        struct timeval tv = {0, 0};
+
+        FD_ZERO(&read_fds);
+        FD_ZERO(&write_fds);
+        FD_SET(fd, &read_fds);
+        FD_SET(fd, &write_fds);
+        ret = select(fd + 1, &read_fds, &write_fds, NULL, &tv);
+    } while (ret < 0 && errno == EINTR);
+
+    if (ret == 1) {
+        if (FD_ISSET(fd, &read_fds)) {
+            result |= PIPE_WAKE_READ;
+        }
+        if (FD_ISSET(fd, &write_fds)) {
+            result |= PIPE_WAKE_WRITE;
+        }
+    }
+#endif
+    return 0;
+}
+
+static void net_pipe_wake_on(void *opaque, int flags)
+{
+    NetPipe *pipe = opaque;
+
+    DD("%s: flags=%d", __FUNCTION__, flags);
+
+    pipe->wakeWanted |= flags;
+    pipe->wakeActual &= ~flags;
+    net_pipe_reset_state(pipe);
+}
+
+/* Called when the pipe finished connecting to its target. |fd| will be -1
+ * to indicate that the connection failed. */
+static void net_pipe_connect_handler(int fd, void* opaque)
+{
+    NetPipe *pipe = opaque;
+
+    if (fd < 0) {
+        net_pipe_close_from_socket(pipe);
+        return;
+    }
+
+    pipe->state = STATE_CONNECTED;
+    net_pipe_reset_state(pipe);
+}
+
+static void *net_pipe_init_from(void *hwpipe,
+                                const char* args,
+                                bool is_unix)
+{
+    if (args == NULL || args[0] == '\0') {
+        D("%s: Missing address!", __FUNCTION__);
+        return NULL;
+    }
+
+    NetPipe *pipe = (NetPipe *)g_new0(NetPipe, 1);
+    pipe->hwpipe = hwpipe;
+    pipe->state = STATE_CONNECTING;
+
+    Error *err = NULL;
+
+    if (is_unix) {
+        D("%s: Unix path is '%s'", __FUNCTION__, args);
+        pipe->fd = unix_nonblocking_connect(args,
+                                            net_pipe_connect_handler,
+                                            pipe,
+                                            &err);
+        if (pipe->fd < 0) {
+            D("%s: Could not connect pipe to %s: %s\n",
+            __FUNCTION__, args, error_get_pretty(err));
+        }
+    } else {
+        D("%s: TCP port is '%s'", __FUNCTION__, args);
+
+        char address[64];
+        snprintf(address, sizeof(address), "127.0.0.1:%s", args);
+
+        pipe->fd = inet_nonblocking_connect(address,
+                                            net_pipe_connect_handler,
+                                            pipe,
+                                            &err);
+        if (pipe->fd < 0) {
+            D("%s: Could not connect pipe to %s: %s\n",
+            __FUNCTION__, address, error_get_pretty(err));
+        }
+    }
+
+    if (pipe->fd < 0) {
+        error_free(err);
+        g_free(pipe);
+        return NULL;
+    }
+
+    return pipe;
+}
+
+static void *net_pipe_init_tcp(void *hwpipe, void *opaque, const char *args)
+{
+    return net_pipe_init_from(hwpipe, args, false);
+}
+
+#ifndef _WIN32
+static void *net_pipe_init_unix(void *hwpipe, void *opaque, const char *args)
+{
+    return net_pipe_init_from(hwpipe, args, true);
+}
+#endif
+
+static const AndroidPipeFuncs net_pipe_tcp_funcs = {
+    net_pipe_init_tcp,
+    net_pipe_close_from_guest,
+    net_pipe_send_buffers,
+    net_pipe_recv_buffers,
+    net_pipe_poll,
+    net_pipe_wake_on,
+    NULL,  /* we can't save these */
+    NULL,  /* we can't load these */
+};
+
+#ifndef _WIN32
+static const AndroidPipeFuncs  net_pipe_unix_funcs = {
+    net_pipe_init_unix,
+    net_pipe_close_from_guest,
+    net_pipe_send_buffers,
+    net_pipe_recv_buffers,
+    net_pipe_poll,
+    net_pipe_wake_on,
+    NULL,  /* we can't save these */
+    NULL,  /* we can't load these */
+};
+#endif
+
+static void *opengles_pipe_init(void *hwpipe,
+                                void *opaque,
+                                const char *args)
+{
+    char server_addr[PATH_MAX];
+    android_gles_server_path(server_addr, sizeof(server_addr));
+    NetPipe *pipe;
+#ifndef _WIN32
+    // Use a Unix pipe on Posix systems.
+    pipe = (NetPipe *)net_pipe_init_unix(hwpipe, opaque, server_addr);
+#else
+    // Use a TCP pipe on Windows.
+    pipe = (NetPipe *)net_pipe_init_tcp(hwpipe, opaque, server_addr);
+#endif
+    if (!pipe) {
+        return NULL;
+    }
+
+    // Disable TCP nagle algorithm to improve through put of small
+    // packets.
+    socket_set_nodelay(pipe->fd);
+
+#ifdef _WIN32
+    // On Windows, adjust buffer sizes.
+    int sndbuf = 128 * 1024;
+    int len = sizeof(sndbuf);
+    if (setsockopt(pipe->fd,
+                    SOL_SOCKET,
+                    SO_SNDBUF,
+                    (char *)&sndbuf,
+                    (int) sizeof(sndbuf)) == SOCKET_ERROR) {
+        D("Failed to set SO_SNDBUF to %d error=0x%x\n",
+            sndbuf, WSAGetLastError());
+    }
+#endif
+    return pipe;
+}
+
+static const AndroidPipeFuncs opengles_pipe_funcs = {
+    opengles_pipe_init,
+    net_pipe_close_from_guest,
+    net_pipe_send_buffers,
+    net_pipe_recv_buffers,
+    net_pipe_poll,
+    net_pipe_wake_on,
+    NULL,  /* we can't save these */
+    NULL,  /* we can't save these */
+};
+
+void
+android_net_pipe_init(void)
+{
+    android_pipe_add_type("tcp", NULL, &net_pipe_tcp_funcs);
+#ifndef _WIN32
+    android_pipe_add_type("unix", NULL, &net_pipe_unix_funcs);
+#endif
+    android_pipe_add_type("opengles", NULL, &opengles_pipe_funcs);
+}
+
diff --git a/hw/misc/android_opengles.c b/hw/misc/android_opengles.c
new file mode 100644
index 0000000..6e12303
--- /dev/null
+++ b/hw/misc/android_opengles.c
@@ -0,0 +1,375 @@
+/*
+ * ARM Android emulator OpenGLES backend
+ *
+ * Copyright (c) 2014 Android Open Source Project
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Handle connections to the 'opengles' pipe from Android guests and route
+ * traffic over this pipe to the GPU emulation libraries.
+ */
+
+#include "hw/misc/android_opengles.h"
+#include "hw/misc/android_pipe.h"
+#include "qemu/compiler.h"
+#include "qemu-common.h"
+
+#include <limits.h>
+
+#ifdef _WIN32
+#include <errno.h>
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+
+// #define DEBUG_OPENGLES
+
+#ifdef DEBUG_OPENGLES
+#define DPRINTF(fmt, ...) \
+do { fprintf(stderr, "adb_debug: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while(0)
+#endif
+
+// Loading shared libraries and probing their symbols.
+typedef struct DynamicLibrary DynamicLibrary;
+
+static DynamicLibrary* dynamic_library_open(const char* library_name)
+{
+    char path[PATH_MAX];
+
+#ifdef _WIN32
+    static const char kDllExtension[] = ".dll";
+#elif defined(__APPLE__)
+    static const char kDllExtension[] = ".dylib";
+#else
+    static const char kDllExtension[] = ".so";
+#endif
+    if (!strchr(library_name, '.')) {
+        snprintf(path, sizeof path, "%s%s", library_name, kDllExtension);
+    } else {
+        snprintf(path, sizeof path, "%s", library_name);
+    }
+#ifdef _WIN32
+    return (DynamicLibrary*)LoadLibrary(path);
+#else
+    return (DynamicLibrary*)dlopen(path, RTLD_NOW);
+#endif
+}
+
+static void dynamic_library_close(DynamicLibrary* library)
+{
+#ifdef _WIN32
+    if (library) {
+        FreeLibrary((HMODULE)library);
+    }
+#else
+    if (library) {
+        dlclose(library);
+    }
+#endif
+}
+
+static void* dynamic_library_probe(DynamicLibrary* library,
+                                   const char* symbol)
+{
+    if (!library || !symbol || !symbol[0]) {
+        return NULL;
+    }
+#ifdef _WIN32
+    return GetProcAddress((HMODULE)library, symbol);
+#else
+    return dlsym(library, symbol);
+#endif
+}
+
+//
+// Loading the GPU shared libraries
+//
+
+// Name of the GLES rendering library we're going to use.
+#if UINTPTR_MAX == UINT32_MAX
+#define RENDERER_LIB_NAME  "libOpenglRender"
+#elif UINTPTR_MAX == UINT64_MAX
+#define RENDERER_LIB_NAME  "lib64OpenglRender"
+#else
+#error Unknown UINTPTR_MAX
+#endif
+
+// NOTE: The declarations below should be equivalent to those in
+// <libOpenglRender/render_api_platform_types.h>
+#ifdef _WIN32
+typedef HDC FBNativeDisplayType;
+typedef HWND FBNativeWindowType;
+#elif defined(__linux__)
+// Really a Window, which is defined as 32-bit unsigned long on all platforms
+// but we don't want to include the X11 headers here.
+typedef uint32_t FBNativeWindowType;
+#elif defined(__APPLE__)
+typedef void* FBNativeWindowType;
+#else
+#warning "unsupported platform"
+#endif
+
+// List of GPU emulation library functions.
+#define RENDERER_FUNCTIONS_LIST \
+  FUNCTION_(int, initLibrary, (void)) \
+  FUNCTION_(int, setStreamMode, (int mode)) \
+  FUNCTION_(int, initOpenGLRenderer, (int width, int height, char* addr, size_t addrLen)) \
+  FUNCTION_(void, getHardwareStrings, (const char** vendors, const char** renderer, const char** version)) \
+  FUNCTION_(void, setPostCallback, (AndroidGLESOnPostFunc onPost, void* onPostContext)) \
+  FUNCTION_(int, createOpenGLSubwindow, (FBNativeWindowType window, int x, int y, int width, int height, float zRot)) \
+  FUNCTION_(int, destroyOpenGLSubwindow, (void)) \
+  FUNCTION_(void, setOpenGLDisplayRotation, (float zRot)) \
+  FUNCTION_(void, repaintOpenGLDisplay, (void)) \
+  FUNCTION_(int, stopOpenGLRenderer, (void)) \
+
+// Name of static variable that points to symbol |name| in the GPU
+// emulation library.
+#define EMUGL_WRAPPER(name)  emugl_ ## name
+
+// Define the corresponding function pointers as global variables, with
+// an 'emugl_' prefix.
+#define FUNCTION_(ret, name, sig) \
+        static ret (*EMUGL_WRAPPER(name)) sig = NULL;
+RENDERER_FUNCTIONS_LIST
+#undef FUNCTION_
+
+
+// Define a function that initializes the function pointers by looking up
+// the symbols from the shared library.
+static int init_opengles_emulation_functions(DynamicLibrary* library)
+{
+    void *symbol;
+
+#define FUNCTION_(ret, name, sig) \
+    symbol = dynamic_library_probe(library, #name); \
+    if (!symbol) { \
+        DPRINTF("GLES emulation: Could not find required symbol (%s): %s\n", #name); \
+        return -1; \
+    } \
+    EMUGL_WRAPPER(name) = symbol;
+
+RENDERER_FUNCTIONS_LIST
+#undef FUNCTION_
+
+    return 0;
+}
+
+// list of constants to be passed to setStreamMode, which determines how
+// to send/receive wire protocol data to/from the library.
+// DEFAULT -> try to use the best for the current platform.
+// TCP -> use a TCP socket to send the protocol bytes to the library.
+// UNIX -> use a Unix domain socket (faster than TCP, but Unix-only).
+// WIN32_PIPE -> use a Win32 PIPE (unsupported by the library for now!).
+enum {
+    STREAM_MODE_DEFAULT = 0,
+    STREAM_MODE_TCP = 1,
+    STREAM_MODE_UNIX = 2,
+    STREAM_MODE_WIN32_PIPE = 3,
+};
+
+struct AndroidGLES {
+    bool init;
+    DynamicLibrary* renderer_lib;
+    bool renderer_started;
+    char renderer_address[256];
+};
+
+static AndroidGLES sState = {
+    .init = false,
+    .renderer_lib = NULL,
+    .renderer_started = false,
+};
+
+AndroidGLES* android_gles_init(void)
+{
+    AndroidGLES* state = &sState;
+
+    if (state->init) {
+        return state;
+    }
+
+    // Try to load the library.
+    state->renderer_lib = dynamic_library_open(RENDERER_LIB_NAME);
+    if (!state->renderer_lib) {
+        DPRINTF("Could not load GPU emulation library!\n");
+        return NULL;
+    }
+
+    // Resolve all required symbols from it.
+    if (init_opengles_emulation_functions(state->renderer_lib) < 0) {
+        DPRINTF("OpenGLES emulation library mismatch. Bes ure to use the correct version!\n");
+        goto BAD_EXIT;
+    }
+
+    // Call its initialization function.
+    if (!EMUGL_WRAPPER(initLibrary)()) {
+        DPRINTF("OpenGLES initialization failed!\n");
+        goto BAD_EXIT;
+    }
+
+#ifdef _WIN32
+    // NOTE: Win32 PIPE support is still not implemented.
+    EMUGL_WRAPPER(setStreamMode)(STREAM_MODE_TCP);
+#else
+    EMUGL_WRAPPER(setStreamMode)(STREAM_MODE_UNIX);
+#endif
+
+    state->init = true;
+    return state;
+
+BAD_EXIT:
+    DPRINTF("OpenGLES library could not be initialized\n");
+    dynamic_library_close(state->renderer_lib);
+
+    state->renderer_lib = NULL;
+    return NULL;
+}
+
+static void extract_base_string(char* dst, const char* src, size_t dstSize)
+{
+    const char* begin = strchr(src, '(');
+    const char* end = strrchr(src, ')');
+
+    if (!begin || !end) {
+        pstrcpy(dst, dstSize, src);
+        return;
+    }
+    begin += 1;
+
+    // "foo (bar)"
+    //       ^  ^
+    //       b  e
+    //     = 5  8
+    // substring with NUL-terminator is end-begin+1 bytes
+    if (end - begin + 1 > dstSize) {
+        end = begin + dstSize - 1;
+    }
+
+    pstrcpy(dst, end - begin + 1, begin);
+}
+
+void android_gles_get_hardware_strings(char *vendor,
+                                       size_t vendor_buffer_size,
+                                       char *renderer,
+                                       size_t renderer_buffer_size,
+                                       char *version,
+                                       size_t version_buffer_size)
+{
+    const char *vendor_src, *renderer_src, *version_src;
+    AndroidGLES *state = &sState;
+
+    if (!state->renderer_started) {
+        DPRINTF("Can't get OpenGL ES hardware strings when renderer not started");
+        vendor[0] = renderer[0] = version[0] = '\0';
+        return;
+    }
+
+    EMUGL_WRAPPER(getHardwareStrings)(&vendor_src,
+                                      &renderer_src,
+                                      &version_src);
+    if (!vendor_src) vendor_src = "";
+    if (!renderer_src) renderer_src = "";
+    if (!version_src) version_src = "";
+
+    /* Special case for the default ES to GL translators: extract the strings
+     * of the underlying OpenGL implementation. */
+    if (strncmp(vendor_src, "Google", 6) == 0 &&
+            strncmp(renderer_src, "Android Emulator OpenGL ES Translator", 37) == 0) {
+        extract_base_string(vendor, vendor_src, vendor_buffer_size);
+        extract_base_string(renderer, renderer_src, renderer_buffer_size);
+        extract_base_string(version, version_src, version_buffer_size);
+    } else {
+        pstrcpy(vendor, vendor_buffer_size, vendor_src);
+        pstrcpy(renderer, renderer_buffer_size, renderer_src);
+        pstrcpy(version, version_buffer_size, version_src);
+    }
+}
+
+int android_gles_start(AndroidGLES* state, int width, int height)
+{
+    if (!state->renderer_lib) {
+        DPRINTF("Can't start OpenGLES renderer without support libraries\n");
+        return -1;
+    }
+
+    if (state->renderer_started) {
+        // Already started.
+        return 0;
+    }
+
+    if (!EMUGL_WRAPPER(initOpenGLRenderer)(
+            width,
+            height,
+            state->renderer_address,
+            sizeof(state->renderer_address))) {
+        DPRINTF("Can't start OpenGLES renderer !?\n");
+        return -1;
+    }
+
+    state->renderer_started = true;
+    return 0;
+}
+
+void android_gles_set_post_callback(AndroidGLES* state,
+                                    AndroidGLESOnPostFunc on_post,
+                                    void* on_post_context)
+{
+    if (state->renderer_lib) {
+        EMUGL_WRAPPER(setPostCallback)(on_post, on_post_context);
+    }
+}
+
+int android_gles_show_window(AndroidGLES* state,
+                             void* window,
+                             int x,
+                             int y,
+                             int width,
+                             int height,
+                             float rotation)
+{
+    if (state->renderer_started) {
+        int success = EMUGL_WRAPPER(createOpenGLSubwindow)(
+                (FBNativeWindowType)(uintptr_t)window,
+                x,
+                y,
+                width,
+                height,
+                rotation);
+        return success ? 0 : -1;
+    } else {
+        return -1;
+    }
+}
+
+void android_gles_hide_window(AndroidGLES* state)
+{
+    if (state->renderer_started) {
+        EMUGL_WRAPPER(destroyOpenGLSubwindow)();
+    }
+}
+
+void android_gles_redraw_window(AndroidGLES* state) {
+    if (state->renderer_started) {
+        EMUGL_WRAPPER(repaintOpenGLDisplay)();
+    }
+}
+
+void android_gles_server_path(char* buff, size_t buff_size)
+{
+    AndroidGLES *state = &sState;
+    pstrcpy(buff, buff_size, state->renderer_address);
+}
diff --git a/include/hw/misc/android_opengles.h b/include/hw/misc/android_opengles.h
new file mode 100644
index 0000000..5a5b59b
--- /dev/null
+++ b/include/hw/misc/android_opengles.h
@@ -0,0 +1,149 @@
+/*
+ * ARM Android emulator OpenGLES backend
+ *
+ * Copyright (c) 2014 Android Open Source Project
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Handle connections to the 'opengles' pipe from Android guests and route
+ * traffic over this pipe to the GPU emulation libraries.
+ */
+
+ #ifndef _HW_MISC_ANDROID_OPENGLES_H
+ #define _HW_MISC_ANDROID_OPENGLES_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* Declarations related to Android-specific GPU emulation support.
+ *
+ * This works as follows:
+ *
+ * - GPU emulation support is implemented by an external shared library
+ *   (e.g. libOpenglRender.so on Linux), which provides a small set of
+ *   well-known entry points.
+ *
+ * - QEMU itself acts as a 'dumb pipe' between the guest system, and
+ *   the GPU emulation library. More specifically:
+ *
+ *     o The guest EGL/GLES system libraries marshall all requests into
+ *       a specific wire protocol stream of bytes. The corresponding data is
+ *       sent directly to QEMU through the "opengles" Android pipe service.
+ *
+ *     o QEMU sends the data directly to the GPU emulation library,
+ *       without trying to process or interpret it. Note that traffic goes
+ *       both ways.
+ *
+ * This design avoids the need for a specific GPU driver in the kernel,
+ * or any knowledge of the wire protocol being used in QEMU itself.
+ *
+ * - The GPU emulation library will display an OpenGL window _on_ _top_ of
+ *   the current window, which will hide the framebuffer completely.
+ *
+ *   To do so, QEMU needs to provide the platform-specific 'id' of the
+ *   current window. See android_gles_show_window() documentation for
+ *   more details.
+ */
+
+/* Opaque data structure modelling the state of GPU emulation support for
+ * Android. */
+typedef struct AndroidGLES AndroidGLES;
+
+/* Initialize the Android GPU emulation support. This function tries to
+ * locate, load and initialize the GPU emulation library, and returns,
+ * on success, a new AndroidGLES instance that can be used to call other
+ * functions below. Return NULL/errno on failure.
+ */
+AndroidGLES* android_gles_init(void);
+
+/* Start GPU emulation support. Returns 0 on success, -1/errno on failure. */
+int android_gles_start(AndroidGLES* state, int width, int height);
+
+/* Retrieve the Vendor/Renderer/Version strings describing the underlying GL
+ * implementation. The call only works while the renderer is started.
+ *
+ * Each string is copied into the corresponding buffer. If the original
+ * string (including NUL terminator) is more than xxBufSize bytes, it will
+ * be truncated. In all cases, including failure, the buffer will be NUL-
+ * terminated when this function returns.
+ */
+void android_gles_get_hardware_strings(char *vendor,
+                                       size_t vendor_buffer_size,
+                                       char *renderer,
+                                       size_t renderer_buffer_size,
+                                       char *version,
+                                       size_t version_buffer_size);
+
+/* Pointer type to a function used to retrieve the content of
+ * GPU framebuffer content. This is used in the Android emulator
+ * to support displaying the framebuffer content to a remote device
+ * for multi-touch support.
+ * |context| is a client-provided value passed to
+ * android_gles_set_post_callback().
+ */
+typedef void (*AndroidGLESOnPostFunc)(void *context,
+                                      int width,
+                                      int height,
+                                      int ydir,
+                                      int format,
+                                      int type,
+                                      unsigned char *pixels);
+
+/* Enable GPU framebuffer retrieval. If |on_post| is not NULL, it will
+ * be called periodically when the framebuffer content changes. Note that
+ * each call can be very expensive, depending on the host GPU.
+ * Set |on_post| to NULL to disable the feature at runtime.
+ */
+void android_gles_set_post_callback(AndroidGLES *gles,
+                                    AndroidGLESOnPostFunc on_post,
+                                    void* on_post_context);
+
+/* Show an OpenGL window on top of the current QEMU UI window, at a
+ * specific location.
+ * |gles| is the current AndroidGLES state.
+ * |window| is a platform-specific identifier for the current UI window
+ * (see note below).
+ * |x|, |y|, |width| and |height| provide the location and size of the
+ * OpenGL window, relative to the current one.
+ * |rotation| is used to provide a rotation angle. Valid values are
+ * 0, 90, 180 and 270.
+ * Returns 0 on success, -1/errno on failure.
+ *
+ * NOTE: The exact type and meaning of |window| depends on the platform:
+ * - On Windows, this is the HWND of the current UI window.
+ * - On Linux, it's the X11 Window identifier (really a uint32_t cast
+ *   to void*).
+ * - On OS X, it's a NSWindow* value.
+ */
+int android_gles_show_window(AndroidGLES *gles,
+                             void *window,
+                             int x,
+                             int y,
+                             int width,
+                             int height,
+                             float rotation);
+
+/* Hide the OpenGL window. */
+void android_gles_hide_window(AndroidGLES *gles);
+
+void android_gles_redraw_window(AndroidGLES *gles);
+
+/* Stop GPU emulation support. */
+void android_gles_stop(AndroidGLES *gles);
+
+/* Write the local GPU server path into buffer |buff| of
+ * |buff_size| bytes. Result is zero-terminated. */
+void android_gles_server_path(char *buff, size_t buff_size);
+
+#endif  /* _HW_MISC_ANDROID_OPENGLES_H */
diff --git a/include/hw/misc/android_pipe.h b/include/hw/misc/android_pipe.h
index 962f2e9..cfba64a 100644
--- a/include/hw/misc/android_pipe.h
+++ b/include/hw/misc/android_pipe.h
@@ -222,6 +222,7 @@
 extern void android_throttle_init(void);
 extern void android_adb_dbg_backend_init(void);
 extern void android_adb_backend_init(void);
+extern void android_net_pipe_init(void);
 
 extern bool adb_server_init(int port);