am bc533dd3: (-s ours) am 18a259fe: am 36ac304c: Merge "Fix for bug 4144936: [Proxy setting]: traffic to a bypass domain doesn\'t bypass proxy DO NOT MERGE" into honeycomb-mr2

* commit 'bc533dd3201afdcf421070cc47250dd7471b77aa':
  Fix for bug 4144936: [Proxy setting]: traffic to a bypass domain doesn't bypass proxy DO NOT MERGE
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
index afa64f8..e34053b 100644
--- a/cmds/keystore/keystore.c
+++ b/cmds/keystore/keystore.c
@@ -493,6 +493,7 @@
     {AID_VPN,      AID_SYSTEM, GET},
     {AID_WIFI,     AID_SYSTEM, GET},
     {AID_ROOT,     AID_SYSTEM, GET},
+    {AID_KEYCHAIN, AID_SYSTEM, TEST | GET | SAW},
     {~0,           ~0,         TEST | GET | INSERT | DELETE | EXIST | SAW},
 };
 
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
index 83cb533..dbff095 100644
--- a/cmds/runtime/main_runtime.cpp
+++ b/cmds/runtime/main_runtime.cpp
@@ -12,7 +12,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
-#include <utils/Log.h>  
+#include <utils/Log.h>
 #include <cutils/zygote.h>
 
 #include <cutils/properties.h>
@@ -41,7 +41,7 @@
 #undef LOG_TAG
 #define LOG_TAG "runtime"
 
-static const char* ZYGOTE_ARGV[] = { 
+static const char* ZYGOTE_ARGV[] = {
     "--setuid=1000",
     "--setgid=1000",
     "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
@@ -68,7 +68,6 @@
 
 namespace android {
 
-extern status_t app_init(const char* className);
 extern void set_finish_init_func(void (*func)());
 
 
@@ -76,7 +75,7 @@
  * This class is used to kill this process (runtime) when the system_server dies.
  */
 class GrimReaper : public IBinder::DeathRecipient {
-public: 
+public:
     GrimReaper() { }
 
     virtual void binderDied(const wp<IBinder>& who)
@@ -170,7 +169,7 @@
 
 /*
  * Post-system-process initialization.
- * 
+ *
  * This function continues initialization after the system process
  * has been initialized.  It needs to be separate because the system
  * initialization needs to care of starting the Android runtime if it is not
@@ -210,17 +209,17 @@
 static void boot_init()
 {
     LOGI("Entered boot_init()!\n");
-    
+
     sp<ProcessState> proc(ProcessState::self());
     LOGD("ProcessState: %p\n", proc.get());
     proc->becomeContextManager(contextChecker, NULL);
-    
+
     if (proc->supportsProcesses()) {
         LOGI("Binder driver opened.  Multiprocess enabled.\n");
     } else {
         LOGI("Binder driver not found.  Processes not supported.\n");
     }
-    
+
     sp<BServiceManager> sm = new BServiceManager;
     proc->setContextObject(sm);
 }
@@ -258,7 +257,7 @@
     int res;
     time_t min_time = 1167652800; // jan 1 2007, type 'date -ud "1/1 12:00" +%s' to get value for current year
     struct timespec ts;
-    
+
     fd = open("/dev/alarm", O_RDWR);
     if(fd < 0) {
         LOGW("Unable to open alarm driver: %s\n", strerror(errno));
@@ -346,14 +345,14 @@
     int ic;
     int result = 1;
     pid_t systemPid;
-    
+
     sp<ProcessState> proc;
 
 #ifndef HAVE_ANDROID_OS
     /* Set stdout/stderr to unbuffered for MinGW/MSYS. */
     //setvbuf(stdout, NULL, _IONBF, 0);
     //setvbuf(stderr, NULL, _IONBF, 0);
-    
+
     LOGI("commandline args:\n");
     for (int i = 0; i < argc; i++)
         LOGI("  %2d: '%s'\n", i, argv[i]);
@@ -455,7 +454,7 @@
 
 #if 0
     // Hack to keep libc from beating the filesystem to death.  It's
-    // hitting /etc/localtime frequently, 
+    // hitting /etc/localtime frequently,
     //
     // This statement locks us into Pacific time.  We could do better,
     // but there's not much point until we're sure that the library
@@ -467,15 +466,15 @@
 
     /* track our progress through the boot sequence */
     const int LOG_BOOT_PROGRESS_START = 3000;
-    LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, 
+    LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
         ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
 
     validateTime();
 
     proc = ProcessState::self();
-    
+
     boot_init();
-    
+
     /* If we are in multiprocess mode, have zygote spawn the system
      * server process and call system_init(). If we are running in
      * single process mode just call system_init() directly.
@@ -488,8 +487,8 @@
         property_get("log.redirect-stdio", propBuf, "");
         logStdio = (strcmp(propBuf, "true") == 0);
 
-        zygote_run_oneshot((int)(!logStdio), 
-                sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]), 
+        zygote_run_oneshot((int)(!logStdio),
+                sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]),
                 ZYGOTE_ARGV);
 
         //start_process("/system/bin/mediaserver");
@@ -497,8 +496,8 @@
     } else {
 #ifndef HAVE_ANDROID_OS
         QuickRuntime* runt = new QuickRuntime();
-        runt->start("com/android/server/SystemServer", 
-                    false /* spontaneously fork system server from zygote */);
+        runt->start("com/android/server/SystemServer",
+                    "" /* spontaneously fork system server from zygote */);
 #endif
     }
 
@@ -506,11 +505,11 @@
 
     finish_system_init(proc);
     run(proc);
-    
+
 bail:
     if (proc != NULL) {
         proc->setContextObject(NULL);
     }
-    
+
     return 0;
 }
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 32c9a1d..bfe13f0 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -53,7 +53,8 @@
     
     status_t            setData(const uint8_t* buffer, size_t len);
 
-    status_t            appendFrom(Parcel *parcel, size_t start, size_t len);
+    status_t            appendFrom(const Parcel *parcel,
+                                   size_t start, size_t len);
 
     bool                hasFileDescriptors() const;
 
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index 168310c..e705c6f 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -31,18 +31,27 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
+class SurfaceTextureClient;
+
 class ISurfaceTexture : public IInterface
 {
 public:
     DECLARE_META_INTERFACE(SurfaceTexture);
 
+protected:
+    friend class SurfaceTextureClient;
+
+    enum {
+        BUFFER_NEEDS_REALLOCATION = 0x1,
+        RELEASE_ALL_BUFFERS       = 0x2,
+    };
+
     // requestBuffer requests a new buffer for the given index. The server (i.e.
     // the ISurfaceTexture implementation) assigns the newly created buffer to
     // the given slot index, and the client is expected to mirror the
     // slot->buffer mapping so that it's not necessary to transfer a
     // GraphicBuffer for every dequeue operation.
-    virtual sp<GraphicBuffer> requestBuffer(int slot, uint32_t w, uint32_t h,
-            uint32_t format, uint32_t usage) = 0;
+    virtual sp<GraphicBuffer> requestBuffer(int slot) = 0;
 
     // setBufferCount sets the number of buffer slots available. Calling this
     // will also cause all buffer slots to be emptied. The caller should empty
@@ -56,14 +65,20 @@
     // should call requestBuffer to assign a new buffer to that slot. The client
     // is expected to either call cancelBuffer on the dequeued slot or to fill
     // in the contents of its associated buffer contents and call queueBuffer.
-    virtual status_t dequeueBuffer(int *slot) = 0;
+    // If dequeueBuffer return BUFFER_NEEDS_REALLOCATION, the client is
+    // expected to call requestBuffer immediately.
+    virtual status_t dequeueBuffer(int *slot, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage) = 0;
 
     // queueBuffer indicates that the client has finished filling in the
     // contents of the buffer associated with slot and transfers ownership of
     // that slot back to the server. It is not valid to call queueBuffer on a
     // slot that is not owned by the client or one for which a buffer associated
-    // via requestBuffer.
-    virtual status_t queueBuffer(int slot) = 0;
+    // via requestBuffer. In addition, a timestamp must be provided by the
+    // client for this buffer. The timestamp is measured in nanoseconds, and
+    // must be monotonically increasing. Its other properties (zero point, etc)
+    // are client-dependent, and should be documented by the client.
+    virtual status_t queueBuffer(int slot, int64_t timestamp) = 0;
 
     // cancelBuffer indicates that the client does not wish to fill in the
     // buffer associated with slot and transfers ownership of the slot back to
@@ -78,6 +93,17 @@
     // Holding this binder reference prevents SurfaceFlinger from freeing the
     // buffers before the client is done with them.
     virtual sp<IBinder> getAllocator() = 0;
+
+    // query retrieves some information for this surface
+    // 'what' tokens allowed are that of android_natives.h
+    virtual int query(int what, int* value) = 0;
+
+    // setSynchronousMode set whether dequeueBuffer is synchronous or
+    // asynchronous. In synchronous mode, dequeueBuffer blocks until
+    // a buffer is available, the currently bound buffer can be dequeued and
+    // queued buffers will be retired in order.
+    // The default mode is asynchronous.
+    virtual status_t setSynchronousMode(bool enabled) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 9bf38f7..43b2fa9 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -34,14 +34,23 @@
 // ----------------------------------------------------------------------------
 
 class IGraphicBufferAlloc;
+class String8;
 
 class SurfaceTexture : public BnSurfaceTexture {
 public:
     enum { MIN_UNDEQUEUED_BUFFERS = 2 };
-    enum { MIN_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1 };
+    enum {
+        MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1,
+        MIN_SYNC_BUFFER_SLOTS  = MIN_UNDEQUEUED_BUFFERS
+    };
     enum { NUM_BUFFER_SLOTS = 32 };
 
     struct FrameAvailableListener : public virtual RefBase {
+        // onFrameAvailable() is called from queueBuffer() is the FIFO is
+        // empty. You can use SurfaceTexture::getQueuedCount() to
+        // figure out if there are more frames waiting.
+        // This is called without any lock held can be called concurrently by
+        // multiple threads.
         virtual void onFrameAvailable() = 0;
     };
 
@@ -56,21 +65,35 @@
     // SurfaceTexture object (i.e. they are not owned by the client).
     virtual status_t setBufferCount(int bufferCount);
 
-    virtual sp<GraphicBuffer> requestBuffer(int buf, uint32_t w, uint32_t h,
-            uint32_t format, uint32_t usage);
+    virtual sp<GraphicBuffer> requestBuffer(int buf);
 
     // dequeueBuffer gets the next buffer slot index for the client to use. If a
     // buffer slot is available then that slot index is written to the location
     // pointed to by the buf argument and a status of OK is returned.  If no
     // slot is available then a status of -EBUSY is returned and buf is
     // unmodified.
-    virtual status_t dequeueBuffer(int *buf);
+    virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage);
 
-    virtual status_t queueBuffer(int buf);
+    // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
+    // timestamp must be provided for the buffer. The timestamp is in
+    // nanoseconds, and must be monotonically increasing. Its other semantics
+    // (zero point, etc) are client-dependent and should be documented by the
+    // client.
+    virtual status_t queueBuffer(int buf, int64_t timestamp);
     virtual void cancelBuffer(int buf);
     virtual status_t setCrop(const Rect& reg);
     virtual status_t setTransform(uint32_t transform);
 
+    virtual int query(int what, int* value);
+
+    // setSynchronousMode set whether dequeueBuffer is synchronous or
+    // asynchronous. In synchronous mode, dequeueBuffer blocks until
+    // a buffer is available, the currently bound buffer can be dequeued and
+    // queued buffers will be retired in order.
+    // The default mode is asynchronous.
+    virtual status_t setSynchronousMode(bool enabled);
+
     // updateTexImage sets the image contents of the target texture to that of
     // the most recently queued buffer.
     //
@@ -78,6 +101,16 @@
     // target texture belongs is bound to the calling thread.
     status_t updateTexImage();
 
+    // getqueuedCount returns the number of queued frames waiting in the
+    // FIFO. In asynchronous mode, this always returns 0 or 1 since
+    // frames are not accumulating in the FIFO.
+    size_t getQueuedCount() const;
+
+    // setBufferCountServer set the buffer count. If the client has requested
+    // a buffer count using setBufferCount, the server-buffer count will
+    // take effect once the client sets the count back to zero.
+    status_t setBufferCountServer(int bufferCount);
+
     // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
     // associated with the texture image set by the most recent call to
     // updateTexImage.
@@ -98,6 +131,14 @@
     // functions.
     void getTransformMatrix(float mtx[16]);
 
+    // getTimestamp retrieves the timestamp associated with the texture image
+    // set by the most recent call to updateTexImage.
+    //
+    // The timestamp is in nanoseconds, and is monotonically increasing. Its
+    // other semantics (zero point, etc) are source-dependent and should be
+    // documented by the source.
+    int64_t getTimestamp();
+
     // setFrameAvailableListener sets the listener object that will be notified
     // when a new frame becomes available.
     void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
@@ -108,19 +149,58 @@
     // buffers before the client is done with them.
     sp<IBinder> getAllocator();
 
-private:
+    // setDefaultBufferSize is used to set the size of buffers returned by
+    // requestBuffers when a with and height of zero is requested.
+    // A call to setDefaultBufferSize() may trigger requestBuffers() to
+    // be called from the client.
+    status_t setDefaultBufferSize(uint32_t w, uint32_t h);
+
+    // getCurrentBuffer returns the buffer associated with the current image.
+    sp<GraphicBuffer> getCurrentBuffer() const;
+
+    // getCurrentTextureTarget returns the texture target of the current
+    // texture as returned by updateTexImage().
+    GLenum getCurrentTextureTarget() const;
+
+    // getCurrentCrop returns the cropping rectangle of the current buffer
+    Rect getCurrentCrop() const;
+
+    // getCurrentTransform returns the transform of the current buffer
+    uint32_t getCurrentTransform() const;
+
+    // dump our state in a String
+    void dump(String8& result) const;
+    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
+
+protected:
 
     // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
     // all slots.
     void freeAllBuffers();
+    static bool isExternalFormat(uint32_t format);
+    static GLenum getTextureTarget(uint32_t format);
+
+private:
 
     // createImage creates a new EGLImage from a GraphicBuffer.
     EGLImageKHR createImage(EGLDisplay dpy,
             const sp<GraphicBuffer>& graphicBuffer);
 
+    status_t setBufferCountServerLocked(int bufferCount);
+
     enum { INVALID_BUFFER_SLOT = -1 };
 
     struct BufferSlot {
+
+        BufferSlot()
+            : mEglImage(EGL_NO_IMAGE_KHR),
+              mEglDisplay(EGL_NO_DISPLAY),
+              mBufferState(BufferSlot::FREE),
+              mRequestBufferCalled(false),
+              mLastQueuedTransform(0),
+              mLastQueuedTimestamp(0) {
+        }
+
         // mGraphicBuffer points to the buffer allocated for this slot or is NULL
         // if no buffer has been allocated.
         sp<GraphicBuffer> mGraphicBuffer;
@@ -131,11 +211,32 @@
         // mEglDisplay is the EGLDisplay used to create mEglImage.
         EGLDisplay mEglDisplay;
 
-        // mOwnedByClient indicates whether the slot is currently accessible to a
+        // mBufferState indicates whether the slot is currently accessible to a
         // client and should not be used by the SurfaceTexture object. It gets
         // set to true when dequeueBuffer returns the slot and is reset to false
         // when the client calls either queueBuffer or cancelBuffer on the slot.
-        bool mOwnedByClient;
+        enum { DEQUEUED=-2, FREE=-1, QUEUED=0 };
+        int8_t mBufferState;
+
+
+        // mRequestBufferCalled is used for validating that the client did
+        // call requestBuffer() when told to do so. Technically this is not
+        // needed but useful for debugging and catching client bugs.
+        bool mRequestBufferCalled;
+
+        // mLastQueuedCrop is the crop rectangle for the buffer that was most
+        // recently queued. This gets set to mNextCrop each time queueBuffer gets
+        // called.
+        Rect mLastQueuedCrop;
+
+        // mLastQueuedTransform is the transform identifier for the buffer that was
+        // most recently queued. This gets set to mNextTransform each time
+        // queueBuffer gets called.
+        uint32_t mLastQueuedTransform;
+
+        // mLastQueuedTimestamp is the timestamp for the buffer that was most
+        // recently queued. This gets set by queueBuffer.
+        int64_t mLastQueuedTimestamp;
     };
 
     // mSlots is the array of buffer slots that must be mirrored on the client
@@ -145,11 +246,31 @@
     // for a slot when requestBuffer is called with that slot's index.
     BufferSlot mSlots[NUM_BUFFER_SLOTS];
 
+    // mDefaultWidth holds the default width of allocated buffers. It is used
+    // in requestBuffers() if a width and height of zero is specified.
+    uint32_t mDefaultWidth;
+
+    // mDefaultHeight holds the default height of allocated buffers. It is used
+    // in requestBuffers() if a width and height of zero is specified.
+    uint32_t mDefaultHeight;
+
+    // mPixelFormat holds the pixel format of allocated buffers. It is used
+    // in requestBuffers() if a format of zero is specified.
+    uint32_t mPixelFormat;
+
     // mBufferCount is the number of buffer slots that the client and server
-    // must maintain. It defaults to MIN_BUFFER_SLOTS and can be changed by
-    // calling setBufferCount.
+    // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
+    // by calling setBufferCount or setBufferCountServer
     int mBufferCount;
 
+    // mRequestedBufferCount is the number of buffer slots requested by the
+    // client. The default is zero, which means the client doesn't care how
+    // many buffers there is.
+    int mClientBufferCount;
+
+    // mServerBufferCount buffer count requested by the server-side
+    int mServerBufferCount;
+
     // mCurrentTexture is the buffer slot index of the buffer that is currently
     // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
     // indicating that no buffer slot is currently bound to the texture. Note,
@@ -158,6 +279,10 @@
     // reset mCurrentTexture to INVALID_BUFFER_SLOT.
     int mCurrentTexture;
 
+    // mCurrentTextureTarget is the GLES texture target to be used with the
+    // current texture.
+    GLenum mCurrentTextureTarget;
+
     // mCurrentTextureBuf is the graphic buffer of the current texture. It's
     // possible that this buffer is not associated with any buffer slot, so we
     // must track it separately in order to properly use
@@ -172,20 +297,9 @@
     // gets set to mLastQueuedTransform each time updateTexImage is called.
     uint32_t mCurrentTransform;
 
-    // mLastQueued is the buffer slot index of the most recently enqueued buffer.
-    // At construction time it is initialized to INVALID_BUFFER_SLOT, and is
-    // updated each time queueBuffer is called.
-    int mLastQueued;
-
-    // mLastQueuedCrop is the crop rectangle for the buffer that was most
-    // recently queued. This gets set to mNextCrop each time queueBuffer gets
-    // called.
-    Rect mLastQueuedCrop;
-
-    // mLastQueuedTransform is the transform identifier for the buffer that was
-    // most recently queued. This gets set to mNextTransform each time
-    // queueBuffer gets called.
-    uint32_t mLastQueuedTransform;
+    // mCurrentTimestamp is the timestamp for the current texture. It
+    // gets set to mLastQueuedTimestamp each time updateTexImage is called.
+    int64_t mCurrentTimestamp;
 
     // mNextCrop is the crop rectangle that will be used for the next buffer
     // that gets queued. It is set by calling setCrop.
@@ -204,21 +318,25 @@
     // allocate new GraphicBuffer objects.
     sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
 
-    // mAllocdBuffers is mirror of the list of buffers that SurfaceFlinger is
-    // referencing. This is kept so that gralloc implementations do not need to
-    // properly handle the case where SurfaceFlinger no longer holds a reference
-    // to a buffer, but other processes do.
-    Vector<sp<GraphicBuffer> > mAllocdBuffers;
-
     // mFrameAvailableListener is the listener object that will be called when a
     // new frame becomes available. If it is not NULL it will be called from
     // queueBuffer.
     sp<FrameAvailableListener> mFrameAvailableListener;
 
+    // mSynchronousMode whether we're in synchronous mode or not
+    bool mSynchronousMode;
+
+    // mDequeueCondition condition used for dequeueBuffer in synchronous mode
+    mutable Condition mDequeueCondition;
+
+    // mQueue is a FIFO of queued buffers used in synchronous mode
+    typedef Vector<int> Fifo;
+    Fifo mQueue;
+
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of SurfaceTexture objects. It must be locked whenever the
     // member variables are accessed.
-    Mutex mMutex;
+    mutable Mutex mMutex;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 7992105..e7c6e24 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -27,6 +27,8 @@
 
 namespace android {
 
+class Surface;
+
 class SurfaceTextureClient
     : public EGLNativeBase<ANativeWindow, SurfaceTextureClient, RefBase>
 {
@@ -36,26 +38,27 @@
     sp<ISurfaceTexture> getISurfaceTexture() const;
 
 private:
+    friend class Surface;
 
     // can't be copied
     SurfaceTextureClient& operator = (const SurfaceTextureClient& rhs);
     SurfaceTextureClient(const SurfaceTextureClient& rhs);
 
     // ANativeWindow hooks
-    static int cancelBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
-    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
-    static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer);
+    static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
     static int perform(ANativeWindow* window, int operation, ...);
-    static int query(ANativeWindow* window, int what, int* value);
-    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int query(const ANativeWindow* window, int what, int* value);
+    static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
     static int setSwapInterval(ANativeWindow* window, int interval);
 
-    int cancelBuffer(android_native_buffer_t* buffer);
-    int dequeueBuffer(android_native_buffer_t** buffer);
-    int lockBuffer(android_native_buffer_t* buffer);
+    int cancelBuffer(ANativeWindowBuffer* buffer);
+    int dequeueBuffer(ANativeWindowBuffer** buffer);
+    int lockBuffer(ANativeWindowBuffer* buffer);
     int perform(int operation, va_list args);
-    int query(int what, int* value);
-    int queueBuffer(android_native_buffer_t* buffer);
+    int query(int what, int* value) const;
+    int queueBuffer(ANativeWindowBuffer* buffer);
     int setSwapInterval(int interval);
 
     int dispatchConnect(va_list args);
@@ -63,6 +66,7 @@
     int dispatchSetBufferCount(va_list args);
     int dispatchSetBuffersGeometry(va_list args);
     int dispatchSetBuffersTransform(va_list args);
+    int dispatchSetBuffersTimestamp(va_list args);
     int dispatchSetCrop(va_list args);
     int dispatchSetUsage(va_list args);
 
@@ -71,13 +75,15 @@
     int setBufferCount(int bufferCount);
     int setBuffersGeometry(int w, int h, int format);
     int setBuffersTransform(int transform);
+    int setBuffersTimestamp(int64_t timestamp);
     int setCrop(Rect const* rect);
     int setUsage(uint32_t reqUsage);
 
     void freeAllBuffers();
 
+    int getConnectedApi() const;
+
     enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS };
-    enum { MIN_BUFFER_SLOTS = SurfaceTexture::MIN_BUFFER_SLOTS };
     enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS };
     enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
 
@@ -114,10 +120,30 @@
     // at the next deuque operation. It is initialized to 0.
     uint32_t mReqUsage;
 
+    // mTimestamp is the timestamp that will be used for the next buffer queue
+    // operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that
+    // a timestamp is auto-generated when queueBuffer is called.
+    int64_t mTimestamp;
+
+    // mConnectedApi holds the currently connected API to this surface
+    int mConnectedApi;
+
+    // mQueryWidth is the width returned by query(). It is set to width
+    // of the last dequeued buffer or to mReqWidth if no buffer was dequeued.
+    uint32_t mQueryWidth;
+
+    // mQueryHeight is the height returned by query(). It is set to height
+    // of the last dequeued buffer or to mReqHeight if no buffer was dequeued.
+    uint32_t mQueryHeight;
+
+    // mQueryFormat is the format returned by query(). It is set to the last
+    // dequeued format or to mReqFormat if no buffer was dequeued.
+    uint32_t mQueryFormat;
+
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of SurfaceTexture objects. It must be locked whenever the
     // member variables are accessed.
-    Mutex mMutex;
+    mutable Mutex mMutex;
 };
 
 }; // namespace android
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index c7db9a6..6b1fa77 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -26,14 +26,11 @@
 #endif
 
 #include <private/pixelflinger/ggl_context.h>
-#include <hardware/copybit.h>
 #include <hardware/gralloc.h>
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
-struct android_native_buffer_t;
-
 namespace android {
 
 
@@ -604,14 +601,6 @@
     void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*);
 };
 
-struct copybits_context_t {
-    // A handle to the blit engine, if it exists, else NULL.
-    copybit_device_t*       blitEngine;
-    int32_t                 minScale;
-    int32_t                 maxScale;
-    android_native_buffer_t* drawSurfaceBuffer;
-};
-
 struct ogles_context_t {
     context_t               rasterizer;
     array_machine_t         arrays         __attribute__((aligned(32)));
@@ -636,13 +625,6 @@
     EGLSurfaceManager*      surfaceManager;
     EGLBufferObjectManager* bufferObjectManager;
 
-    // copybits is only used if LIBAGL_USE_GRALLOC_COPYBITS is
-    // defined, but it is always present because ogles_context_t is a public
-    // struct that is used by clients of libagl. We want the size and offsets
-    // to stay the same, whether or not LIBAGL_USE_GRALLOC_COPYBITS is defined.
-
-    copybits_context_t      copybits;
-
     GLenum                  error;
 
     static inline ogles_context_t* get() {
diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h
index d996af7..01e4bd9 100644
--- a/include/surfaceflinger/IGraphicBufferAlloc.h
+++ b/include/surfaceflinger/IGraphicBufferAlloc.h
@@ -32,18 +32,10 @@
 public:
     DECLARE_META_INTERFACE(GraphicBufferAlloc);
 
-    /* Create a new GraphicBuffer for the client to use.  The server will
-     * maintain a reference to the newly created GraphicBuffer until
-     * freeAllGraphicBuffers is called.
+    /* Create a new GraphicBuffer for the client to use.
      */
     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
             PixelFormat format, uint32_t usage) = 0;
-
-    /* Free all but one of the GraphicBuffer objects that the server is
-     * currently referencing. If bufIndex is not a valid index of the buffers
-     * the server is referencing, then all buffers are freed.
-     */
-    virtual void freeAllGraphicBuffersExcept(int bufIndex) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index a1e9e04..46b1bb7 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -64,7 +64,6 @@
      * Requires ACCESS_SURFACE_FLINGER permission
      */
     virtual sp<ISurface> createSurface( surface_data_t* data,
-                                        int pid,
                                         const String8& name,
                                         DisplayID display,
                                         uint32_t w,
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 9e0b5bb..ab30f45 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -102,10 +102,6 @@
     friend class Test;
     // videoEditor preview classes
     friend class VideoEditorPreviewController;
-
-    const sp<ISurface>& getISurface() const { return mSurface; }
-    
-
     friend class Surface;
 
     SurfaceControl(
@@ -169,6 +165,7 @@
     // setSwapRectangle() is intended to be used by GL ES clients
     void        setSwapRectangle(const Rect& r);
 
+    sp<IBinder> asBinder() const;
 
 private:
     /*
@@ -205,18 +202,18 @@
      *  ANativeWindow hooks
      */
     static int setSwapInterval(ANativeWindow* window, int interval);
-    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
-    static int cancelBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
-    static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
-    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
-    static int query(ANativeWindow* window, int what, int* value);
+    static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer);
+    static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int query(const ANativeWindow* window, int what, int* value);
     static int perform(ANativeWindow* window, int operation, ...);
 
-    int dequeueBuffer(android_native_buffer_t** buffer);
-    int lockBuffer(android_native_buffer_t* buffer);
-    int queueBuffer(android_native_buffer_t* buffer);
-    int cancelBuffer(android_native_buffer_t* buffer);
-    int query(int what, int* value);
+    int dequeueBuffer(ANativeWindowBuffer** buffer);
+    int lockBuffer(ANativeWindowBuffer* buffer);
+    int queueBuffer(ANativeWindowBuffer* buffer);
+    int cancelBuffer(ANativeWindowBuffer* buffer);
+    int query(int what, int* value) const;
     int perform(int operation, va_list args);
 
     void dispatch_setUsage(va_list args);
@@ -226,7 +223,8 @@
     int  dispatch_set_buffer_count(va_list args);
     int  dispatch_set_buffers_geometry(va_list args);
     int  dispatch_set_buffers_transform(va_list args);
-    
+    int  dispatch_set_buffers_timestamp(va_list args);
+
     void setUsage(uint32_t reqUsage);
     int  connect(int api);
     int  disconnect(int api);
@@ -234,13 +232,13 @@
     int  setBufferCount(int bufferCount);
     int  setBuffersGeometry(int w, int h, int format);
     int  setBuffersTransform(int transform);
+    int  setBuffersTimestamp(int64_t timestamp);
 
     /*
      *  private stuff...
      */
     void init();
     status_t validate(bool inCancelBuffer = false) const;
-    sp<ISurface> getISurface() const;
 
     // When the buffer pool is a fixed size we want to make sure SurfaceFlinger
     // won't stall clients, so we require an extra buffer.
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 25b2ebf..c61a5bf 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -79,7 +79,6 @@
 
     //! Create a surface
     sp<SurfaceControl> createSurface(
-            int pid,            // pid of the process the surface is for
             const String8& name,// name of the surface
             DisplayID display,  // Display to create this surface on
             uint32_t w,         // width in pixel
@@ -89,7 +88,6 @@
     );
 
     sp<SurfaceControl> createSurface(
-            int pid,            // pid of the process the surface is for
             DisplayID display,  // Display to create this surface on
             uint32_t w,         // width in pixel
             uint32_t h,         // height in pixel
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
deleted file mode 100644
index 998e353..0000000
--- a/include/tts/TtsEngine.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <media/AudioSystem.h>
-
-// This header defines the interface used by the Android platform
-// to access Text-To-Speech functionality in shared libraries that implement
-// speech synthesis and the management of resources associated with the
-// synthesis.
-// An example of the implementation of this interface can be found in
-// FIXME: add path+name to implementation of default TTS engine
-// Libraries implementing this interface are used in:
-//  frameworks/base/tts/jni/android_tts_SpeechSynthesis.cpp
-
-namespace android {
-
-#define ANDROID_TTS_ENGINE_PROPERTY_CONFIG "engineConfig"
-#define ANDROID_TTS_ENGINE_PROPERTY_PITCH  "pitch"
-#define ANDROID_TTS_ENGINE_PROPERTY_RATE   "rate"
-#define ANDROID_TTS_ENGINE_PROPERTY_VOLUME "volume"
-
-
-enum tts_synth_status {
-    TTS_SYNTH_DONE              = 0,
-    TTS_SYNTH_PENDING           = 1
-};
-
-enum tts_callback_status {
-    TTS_CALLBACK_HALT           = 0,
-    TTS_CALLBACK_CONTINUE       = 1
-};
-
-// The callback is used by the implementation of this interface to notify its
-// client, the Android TTS service, that the last requested synthesis has been
-// completed. // TODO reword
-// The callback for synthesis completed takes:
-// @param [inout] void *&       - The userdata pointer set in the original
-//                                 synth call
-// @param [in]    uint32_t      - Track sampling rate in Hz
-// @param [in]    uint32_t      - The audio format
-// @param [in]    int           - The number of channels
-// @param [inout] int8_t *&     - A buffer of audio data only valid during the
-//                                execution of the callback
-// @param [inout] size_t  &     - The size of the buffer
-// @param [in] tts_synth_status - indicate whether the synthesis is done, or
-//                                 if more data is to be synthesized.
-// @return TTS_CALLBACK_HALT to indicate the synthesis must stop,
-//         TTS_CALLBACK_CONTINUE to indicate the synthesis must continue if
-//            there is more data to produce.
-typedef tts_callback_status (synthDoneCB_t)(void *&, uint32_t,
-        uint32_t, int, int8_t *&, size_t&, tts_synth_status);
-
-class TtsEngine;
-extern "C" TtsEngine* getTtsEngine();
-
-enum tts_result {
-    TTS_SUCCESS                 = 0,
-    TTS_FAILURE                 = -1,
-    TTS_FEATURE_UNSUPPORTED     = -2,
-    TTS_VALUE_INVALID           = -3,
-    TTS_PROPERTY_UNSUPPORTED    = -4,
-    TTS_PROPERTY_SIZE_TOO_SMALL = -5,
-    TTS_MISSING_RESOURCES       = -6
-};
-
-enum tts_support_result {
-    TTS_LANG_COUNTRY_VAR_AVAILABLE = 2,
-    TTS_LANG_COUNTRY_AVAILABLE = 1,
-    TTS_LANG_AVAILABLE = 0,
-    TTS_LANG_MISSING_DATA = -1,
-    TTS_LANG_NOT_SUPPORTED = -2
-};
-
-class TtsEngine
-{
-public:
-    virtual ~TtsEngine() {}
-
-    // Initialize the TTS engine and returns whether initialization succeeded.
-    // @param synthDoneCBPtr synthesis callback function pointer
-    // @return TTS_SUCCESS, or TTS_FAILURE
-    virtual tts_result init(synthDoneCB_t synthDoneCBPtr, const char *engineConfig);
-
-    // Shut down the TTS engine and releases all associated resources.
-    // @return TTS_SUCCESS, or TTS_FAILURE
-    virtual tts_result shutdown();
-
-    // Interrupt synthesis and flushes any synthesized data that hasn't been
-    // output yet. This will block until callbacks underway are completed.
-    // @return TTS_SUCCESS, or TTS_FAILURE
-    virtual tts_result stop();
-
-    // Returns the level of support for the language, country and variant.
-    // @return TTS_LANG_COUNTRY_VAR_AVAILABLE if the language, country and variant are supported,
-    //            and the corresponding resources are correctly installed
-    //         TTS_LANG_COUNTRY_AVAILABLE if the language and country are supported and the
-    //             corresponding resources are correctly installed, but there is no match for
-    //             the specified variant
-    //         TTS_LANG_AVAILABLE if the language is supported and the
-    //             corresponding resources are correctly installed, but there is no match for
-    //             the specified country and variant
-    //         TTS_LANG_MISSING_DATA if the required resources to provide any level of support
-    //             for the language are not correctly installed
-    //         TTS_LANG_NOT_SUPPORTED if the language is not supported by the TTS engine.
-    virtual tts_support_result isLanguageAvailable(const char *lang, const char *country,
-            const char *variant);
-
-    // Load the resources associated with the specified language. The loaded
-    // language will only be used once a call to setLanguage() with the same
-    // language value is issued. Language and country values are coded according to the ISO three
-    // letter codes for languages and countries, as can be retrieved from a java.util.Locale
-    // instance. The variant value is encoded as the variant string retrieved from a
-    // java.util.Locale instance built with that variant data.
-    // @param lang pointer to the ISO three letter code for the language
-    // @param country pointer to the ISO three letter code for the country
-    // @param variant pointer to the variant code
-    // @return TTS_SUCCESS, or TTS_FAILURE
-    virtual tts_result loadLanguage(const char *lang, const char *country, const char *variant);
-
-    // Load the resources associated with the specified language, country and Locale variant.
-    // The loaded language will only be used once a call to setLanguageFromLocale() with the same
-    // language value is issued. Language and country values are coded according to the ISO three
-    // letter codes for languages and countries, as can be retrieved from a java.util.Locale
-    // instance. The variant value is encoded as the variant string retrieved from a
-    // java.util.Locale instance built with that variant data.
-    // @param lang pointer to the ISO three letter code for the language
-    // @param country pointer to the ISO three letter code for the country
-    // @param variant pointer to the variant code
-    // @return TTS_SUCCESS, or TTS_FAILURE
-    virtual tts_result setLanguage(const char *lang, const char *country, const char *variant);
-
-    // Retrieve the currently set language, country and variant, or empty strings if none of
-    // parameters have been set. Language and country are represented by their 3-letter ISO code
-    // @param[out]   pointer to the retrieved 3-letter code language value
-    // @param[out]   pointer to the retrieved 3-letter code country value
-    // @param[out]   pointer to the retrieved variant value
-    // @return TTS_SUCCESS, or TTS_FAILURE
-    virtual tts_result getLanguage(char *language, char *country, char *variant);
-
-    // Notifies the engine what audio parameters should be used for the synthesis.
-    // This is meant to be used as a hint, the engine implementation will set the output values
-    // to those of the synthesis format, based on a given hint.
-    // @param[inout] encoding in: the desired audio sample format
-    //                         out: the format used by the TTS engine
-    // @param[inout] rate in: the desired audio sample rate
-    //                         out: the sample rate used by the TTS engine
-    // @param[inout] channels in: the desired number of audio channels
-    //                         out: the number of channels used by the TTS engine
-    // @return TTS_SUCCESS, or TTS_FAILURE
-    virtual tts_result setAudioFormat(AudioSystem::audio_format& encoding, uint32_t& rate,
-            int& channels);
-
-    // Set a property for the the TTS engine
-    // "size" is the maximum size of "value" for properties "property"
-    // @param property pointer to the property name
-    // @param value    pointer to the property value
-    // @param size     maximum size required to store this type of property
-    // @return         TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_FAILURE,
-    //                  or TTS_VALUE_INVALID
-    virtual tts_result setProperty(const char *property, const char *value,
-            const size_t size);
-
-    // Retrieve a property from the TTS engine
-    // @param        property pointer to the property name
-    // @param[out]   value    pointer to the retrieved language value
-    // @param[inout] iosize   in: stores the size available to store the
-    //                          property value.
-    //                        out: stores the size required to hold the language
-    //                          value if getLanguage() returned
-    //                          TTS_PROPERTY_SIZE_TOO_SMALL, unchanged otherwise
-    // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS,
-    //         or TTS_PROPERTY_SIZE_TOO_SMALL
-    virtual tts_result getProperty(const char *property, char *value,
-            size_t *iosize);
-
-    // Synthesize the text.
-    // As the synthesis is performed, the engine invokes the callback to notify
-    // the TTS framework that it has filled the given buffer, and indicates how
-    // many bytes it wrote. The callback is called repeatedly until the engine
-    // has generated all the audio data corresponding to the text.
-    // Note about the format of the input: the text parameter may use the
-    // following elements
-    // and their respective attributes as defined in the SSML 1.0 specification:
-    //    * lang
-    //    * say-as:
-    //          o interpret-as
-    //    * phoneme
-    //    * voice:
-    //          o gender,
-    //          o age,
-    //          o variant,
-    //          o name
-    //    * emphasis
-    //    * break:
-    //          o strength,
-    //          o time
-    //    * prosody:
-    //          o pitch,
-    //          o contour,
-    //          o range,
-    //          o rate,
-    //          o duration,
-    //          o volume
-    //    * mark
-    // Differences between this text format and SSML are:
-    //    * full SSML documents are not supported
-    //    * namespaces are not supported
-    // Text is coded in UTF-8.
-    // @param text      the UTF-8 text to synthesize
-    // @param userdata  pointer to be returned when the call is invoked
-    // @param buffer    the location where the synthesized data must be written
-    // @param bufferSize the number of bytes that can be written in buffer
-    // @return          TTS_SUCCESS or TTS_FAILURE
-    virtual tts_result synthesizeText(const char *text, int8_t *buffer,
-            size_t bufferSize, void *userdata);
-
-};
-
-} // namespace android
-
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index 16117ad..302d012 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -67,10 +67,10 @@
     friend class LightRefBase<FramebufferNativeWindow>;    
     ~FramebufferNativeWindow(); // this class cannot be overloaded
     static int setSwapInterval(ANativeWindow* window, int interval);
-    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
-    static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
-    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
-    static int query(ANativeWindow* window, int what, int* value);
+    static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer);
+    static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int query(const ANativeWindow* window, int what, int* value);
     static int perform(ANativeWindow* window, int operation, ...);
     
     framebuffer_device_t* fbDev;
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 02d6f8f..370253a 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -26,7 +26,7 @@
 #include <utils/Flattenable.h>
 #include <pixelflinger/pixelflinger.h>
 
-struct android_native_buffer_t;
+struct ANativeWindowBuffer;
 
 namespace android {
 
@@ -38,7 +38,7 @@
 
 class GraphicBuffer
     : public EGLNativeBase<
-        android_native_buffer_t, 
+        ANativeWindowBuffer,
         GraphicBuffer, 
         LightRefBase<GraphicBuffer> >, public Flattenable
 {
@@ -74,8 +74,8 @@
     GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
             uint32_t stride, native_handle_t* handle, bool keepOwnership);
 
-    // create a buffer from an existing android_native_buffer_t
-    GraphicBuffer(android_native_buffer_t* buffer, bool keepOwnership);
+    // create a buffer from an existing ANativeWindowBuffer
+    GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership);
 
     // return status
     status_t initCheck() const;
@@ -94,7 +94,7 @@
     status_t lock(GGLSurface* surface, uint32_t usage);
     status_t unlock();
 
-    android_native_buffer_t* getNativeBuffer() const;
+    ANativeWindowBuffer* getNativeBuffer() const;
     
     void setIndex(int index);
     int getIndex() const;
@@ -149,7 +149,7 @@
 
     // If we're wrapping another buffer then this reference will make sure it
     // doesn't get freed.
-    sp<android_native_buffer_t> mWrappedBuffer;
+    sp<ANativeWindowBuffer> mWrappedBuffer;
 };
 
 }; // namespace android
diff --git a/include/ui/Input.h b/include/ui/Input.h
index bc5b718..ba1c6b4 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -27,6 +27,7 @@
 #include <utils/Timers.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
+#include <utils/BitSet.h>
 
 #ifdef HAVE_ANDROID_OS
 class SkMatrix;
@@ -36,10 +37,16 @@
  * Additional private constants not defined in ndk/ui/input.h.
  */
 enum {
-    /*
-     * Private control to determine when an app is tracking a key sequence.
-     */
-    AKEY_EVENT_FLAG_START_TRACKING = 0x40000000
+    /* Private control to determine when an app is tracking a key sequence. */
+    AKEY_EVENT_FLAG_START_TRACKING = 0x40000000,
+
+    /* Key event is inconsistent with previously sent key events. */
+    AKEY_EVENT_FLAG_TAINTED = 0x80000000,
+};
+
+enum {
+    /* Motion event is inconsistent with previously sent motion events. */
+    AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
 };
 
 enum {
@@ -127,6 +134,12 @@
     // input device or an application with system-wide event injection permission.
     POLICY_FLAG_TRUSTED = 0x02000000,
 
+    // Indicates that the input event has passed through an input filter.
+    POLICY_FLAG_FILTERED = 0x04000000,
+
+    // Disables automatic key repeating behavior.
+    POLICY_FLAG_DISABLE_KEY_REPEAT = 0x08000000,
+
     /* These flags are set by the input reader policy as it intercepts each event. */
 
     // Indicates that the screen was off when the event was received and the event
@@ -144,14 +157,6 @@
 };
 
 /*
- * Button state.
- */
-enum {
-    // Primary button pressed (left mouse button).
-    BUTTON_STATE_PRIMARY = 1 << 0,
-};
-
-/*
  * Describes the basic configuration of input devices that are present.
  */
 struct InputConfiguration {
@@ -210,11 +215,41 @@
     status_t writeToParcel(Parcel* parcel) const;
 #endif
 
+    bool operator==(const PointerCoords& other) const;
+    inline bool operator!=(const PointerCoords& other) const {
+        return !(*this == other);
+    }
+
+    void copyFrom(const PointerCoords& other);
+
 private:
     void tooManyAxes(int axis);
 };
 
 /*
+ * Pointer property data.
+ */
+struct PointerProperties {
+    // The id of the pointer.
+    int32_t id;
+
+    // The pointer tool type.
+    int32_t toolType;
+
+    inline void clear() {
+        id = -1;
+        toolType = 0;
+    }
+
+    bool operator==(const PointerProperties& other) const;
+    inline bool operator!=(const PointerProperties& other) const {
+        return !(*this == other);
+    }
+
+    void copyFrom(const PointerProperties& other);
+};
+
+/*
  * Input events.
  */
 class InputEvent : public AInputEvent {
@@ -305,10 +340,19 @@
 
     inline int32_t getAction() const { return mAction; }
 
+    inline int32_t getActionMasked() const { return mAction & AMOTION_EVENT_ACTION_MASK; }
+
+    inline int32_t getActionIndex() const {
+        return (mAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
+                >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+    }
+
     inline void setAction(int32_t action) { mAction = action; }
 
     inline int32_t getFlags() const { return mFlags; }
 
+    inline void setFlags(int32_t flags) { mFlags = flags; }
+
     inline int32_t getEdgeFlags() const { return mEdgeFlags; }
 
     inline void setEdgeFlags(int32_t edgeFlags) { mEdgeFlags = edgeFlags; }
@@ -317,6 +361,8 @@
 
     inline void setMetaState(int32_t metaState) { mMetaState = metaState; }
 
+    inline int32_t getButtonState() const { return mButtonState; }
+
     inline float getXOffset() const { return mXOffset; }
 
     inline float getYOffset() const { return mYOffset; }
@@ -327,9 +373,21 @@
 
     inline nsecs_t getDownTime() const { return mDownTime; }
 
-    inline size_t getPointerCount() const { return mPointerIds.size(); }
+    inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; }
 
-    inline int32_t getPointerId(size_t pointerIndex) const { return mPointerIds[pointerIndex]; }
+    inline size_t getPointerCount() const { return mPointerProperties.size(); }
+
+    inline const PointerProperties* getPointerProperties(size_t pointerIndex) const {
+        return &mPointerProperties[pointerIndex];
+    }
+
+    inline int32_t getPointerId(size_t pointerIndex) const {
+        return mPointerProperties[pointerIndex].id;
+    }
+
+    inline int32_t getToolType(size_t pointerIndex) const {
+        return mPointerProperties[pointerIndex].toolType;
+    }
 
     inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; }
 
@@ -452,6 +510,8 @@
                 AMOTION_EVENT_AXIS_ORIENTATION, pointerIndex, historicalIndex);
     }
 
+    ssize_t findPointerIndex(int32_t pointerId) const;
+
     void initialize(
             int32_t deviceId,
             int32_t source,
@@ -459,6 +519,7 @@
             int32_t flags,
             int32_t edgeFlags,
             int32_t metaState,
+            int32_t buttonState,
             float xOffset,
             float yOffset,
             float xPrecision,
@@ -466,7 +527,7 @@
             nsecs_t downTime,
             nsecs_t eventTime,
             size_t pointerCount,
-            const int32_t* pointerIds,
+            const PointerProperties* pointerProperties,
             const PointerCoords* pointerCoords);
 
     void copyFrom(const MotionEvent* other, bool keepHistory);
@@ -492,7 +553,9 @@
     }
 
     // Low-level accessors.
-    inline const int32_t* getPointerIds() const { return mPointerIds.array(); }
+    inline const PointerProperties* getPointerProperties() const {
+        return mPointerProperties.array();
+    }
     inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); }
     inline const PointerCoords* getSamplePointerCoords() const {
             return mSamplePointerCoords.array();
@@ -503,12 +566,13 @@
     int32_t mFlags;
     int32_t mEdgeFlags;
     int32_t mMetaState;
+    int32_t mButtonState;
     float mXOffset;
     float mYOffset;
     float mXPrecision;
     float mYPrecision;
     nsecs_t mDownTime;
-    Vector<int32_t> mPointerIds;
+    Vector<PointerProperties> mPointerProperties;
     Vector<nsecs_t> mSampleEventTimes;
     Vector<PointerCoords> mSamplePointerCoords;
 };
@@ -545,6 +609,72 @@
 };
 
 /*
+ * Calculates the velocity of pointer movements over time.
+ */
+class VelocityTracker {
+public:
+    struct Position {
+        float x, y;
+    };
+
+    VelocityTracker();
+
+    // Resets the velocity tracker state.
+    void clear();
+
+    // Resets the velocity tracker state for specific pointers.
+    // Call this method when some pointers have changed and may be reusing
+    // an id that was assigned to a different pointer earlier.
+    void clearPointers(BitSet32 idBits);
+
+    // Adds movement information for a set of pointers.
+    // The idBits bitfield specifies the pointer ids of the pointers whose positions
+    // are included in the movement.
+    // The positions array contains position information for each pointer in order by
+    // increasing id.  Its size should be equal to the number of one bits in idBits.
+    void addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions);
+
+    // Adds movement information for all pointers in a MotionEvent, including historical samples.
+    void addMovement(const MotionEvent* event);
+
+    // Gets the velocity of the specified pointer id in position units per second.
+    // Returns false and sets the velocity components to zero if there is no movement
+    // information for the pointer.
+    bool getVelocity(uint32_t id, float* outVx, float* outVy) const;
+
+    // Gets the active pointer id, or -1 if none.
+    inline int32_t getActivePointerId() const { return mActivePointerId; }
+
+    // Gets a bitset containing all pointer ids from the most recent movement.
+    inline BitSet32 getCurrentPointerIdBits() const { return mMovements[mIndex].idBits; }
+
+private:
+    // Number of samples to keep.
+    static const uint32_t HISTORY_SIZE = 10;
+
+    // Oldest sample to consider when calculating the velocity.
+    static const nsecs_t MAX_AGE = 200 * 1000000; // 200 ms
+
+    // When the total duration of the window of samples being averaged is less
+    // than the window size, the resulting velocity is scaled to reduce the impact
+    // of overestimation in short traces.
+    static const nsecs_t MIN_WINDOW = 100 * 1000000; // 100 ms
+
+    // The minimum duration between samples when estimating velocity.
+    static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms
+
+    struct Movement {
+        nsecs_t eventTime;
+        BitSet32 idBits;
+        Position positions[MAX_POINTERS];
+    };
+
+    uint32_t mIndex;
+    Movement mMovements[HISTORY_SIZE];
+    int32_t mActivePointerId;
+};
+
+/*
  * Describes the characteristics and capabilities of an input device.
  */
 class InputDeviceInfo {
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 119db81..95e4447 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -136,6 +136,7 @@
             int32_t action;
             int32_t flags;
             int32_t metaState;
+            int32_t buttonState;
             int32_t edgeFlags;
             nsecs_t downTime;
             float xOffset;
@@ -143,7 +144,7 @@
             float xPrecision;
             float yPrecision;
             size_t pointerCount;
-            int32_t pointerIds[MAX_POINTERS];
+            PointerProperties pointerProperties[MAX_POINTERS];
             size_t sampleCount;
             SampleData sampleData[0]; // variable length
         } motion;
@@ -221,6 +222,7 @@
             int32_t flags,
             int32_t edgeFlags,
             int32_t metaState,
+            int32_t buttonState,
             float xOffset,
             float yOffset,
             float xPrecision,
@@ -228,7 +230,7 @@
             nsecs_t downTime,
             nsecs_t eventTime,
             size_t pointerCount,
-            const int32_t* pointerIds,
+            const PointerProperties* pointerProperties,
             const PointerCoords* pointerCoords);
 
     /* Appends a motion sample to a motion event unless already consumed.
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index b912e9b..8383957 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -228,6 +228,9 @@
     { "BUTTON_14", 201 },
     { "BUTTON_15", 202 },
     { "BUTTON_16", 203 },
+    { "LANGUAGE_SWITCH", 204 },
+    { "MANNER_MODE", 205 },
+    { "3D_MODE", 206 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 925fd06..6c9a620 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -24,8 +24,6 @@
 
 #include <ui/Rect.h>
 
-#include <hardware/copybit.h>
-
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -183,27 +181,6 @@
 Region& Region::operator += (const Point& pt) {
     return translateSelf(pt.x, pt.y);
 }
-
-// ---------------------------------------------------------------------------
-
-struct region_iterator : public copybit_region_t {
-    region_iterator(const Region& region)
-        : b(region.begin()), e(region.end()) {
-        this->next = iterate;
-    }
-private:
-    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
-        region_iterator const* me = static_cast<region_iterator const*>(self);
-        if (me->b != me->e) {
-            *reinterpret_cast<Rect*>(rect) = *me->b++;
-            return 1;
-        }
-        return 0;
-    }
-    mutable Region::const_iterator b;
-    Region::const_iterator const e;
-};
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/include/ui/android_native_buffer.h b/include/ui/android_native_buffer.h
index 402843e..b6e1db4 100644
--- a/include/ui/android_native_buffer.h
+++ b/include/ui/android_native_buffer.h
@@ -19,53 +19,4 @@
 
 #include <ui/egl/android_natives.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*****************************************************************************/
-
-typedef struct android_native_buffer_t
-{
-#ifdef __cplusplus
-    android_native_buffer_t() { 
-        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
-        common.version = sizeof(android_native_buffer_t);
-        memset(common.reserved, 0, sizeof(common.reserved));
-    }
-
-    // Implement the methods that sp<android_native_buffer_t> expects so that it
-    // can be used to automatically refcount android_native_buffer_t's.
-    void incStrong(const void* id) const {
-        common.incRef(const_cast<android_native_base_t*>(&common));
-    }
-    void decStrong(const void* id) const {
-        common.decRef(const_cast<android_native_base_t*>(&common));
-    }
-#endif
-
-    struct android_native_base_t common;
-
-    int width;
-    int height;
-    int stride;
-    int format;
-    int usage;
-    
-    void* reserved[2];
-
-    buffer_handle_t handle;
-
-    void* reserved_proc[8];
-} android_native_buffer_t;
-
-
-/*****************************************************************************/
-
-#ifdef __cplusplus
-}
-#endif
-
-/*****************************************************************************/
-
 #endif /* ANDROID_ANDROID_NATIVES_PRIV_H */
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 0fc1ddf..9ac50a5 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -21,374 +21,9 @@
 #include <string.h>
 
 #include <hardware/gralloc.h>
-
+#include <system/window.h>
+// FIXME: remove this header, it's for legacy use.  native_window is pulled from frameworks/base/native/include/android/
 #include <android/native_window.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*****************************************************************************/
-
-#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
-    (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d))
-
-#define ANDROID_NATIVE_WINDOW_MAGIC \
-    ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
-
-#define ANDROID_NATIVE_BUFFER_MAGIC \
-    ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
-
-// ---------------------------------------------------------------------------
-
-struct android_native_buffer_t;
-
-typedef struct android_native_rect_t
-{
-    int32_t left;
-    int32_t top;
-    int32_t right;
-    int32_t bottom;
-} android_native_rect_t;
-
-// ---------------------------------------------------------------------------
-
-typedef struct android_native_base_t
-{
-    /* a magic value defined by the actual EGL native type */
-    int magic;
-    
-    /* the sizeof() of the actual EGL native type */
-    int version;
-
-    void* reserved[4];
-
-    /* reference-counting interface */
-    void (*incRef)(struct android_native_base_t* base);
-    void (*decRef)(struct android_native_base_t* base);
-} android_native_base_t;
-
-// ---------------------------------------------------------------------------
-
-/* attributes queriable with query() */
-enum {
-    NATIVE_WINDOW_WIDTH     = 0,
-    NATIVE_WINDOW_HEIGHT,
-    NATIVE_WINDOW_FORMAT,
-
-    /* The minimum number of buffers that must remain un-dequeued after a buffer
-     * has been queued.  This value applies only if set_buffer_count was used to
-     * override the number of buffers and if a buffer has since been queued.
-     * Users of the set_buffer_count ANativeWindow method should query this
-     * value before calling set_buffer_count.  If it is necessary to have N
-     * buffers simultaneously dequeued as part of the steady-state operation,
-     * and this query returns M then N+M buffers should be requested via
-     * native_window_set_buffer_count.
-     *
-     * Note that this value does NOT apply until a single buffer has been
-     * queued.  In particular this means that it is possible to:
-     *
-     * 1. Query M = min undequeued buffers
-     * 2. Set the buffer count to N + M
-     * 3. Dequeue all N + M buffers
-     * 4. Cancel M buffers
-     * 5. Queue, dequeue, queue, dequeue, ad infinitum
-     */
-    NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
-
-    /* Check whether queueBuffer operations on the ANativeWindow send the buffer
-     * to the window compositor.  The query sets the returned 'value' argument
-     * to 1 if the ANativeWindow DOES send queued buffers directly to the window
-     * compositor and 0 if the buffers do not go directly to the window
-     * compositor.
-     *
-     * This can be used to determine whether protected buffer content should be
-     * sent to the ANativeWindow.  Note, however, that a result of 1 does NOT
-     * indicate that queued buffers will be protected from applications or users
-     * capturing their contents.  If that behavior is desired then some other
-     * mechanism (e.g. the GRALLOC_USAGE_PROTECTED flag) should be used in
-     * conjunction with this query.
-     */
-    NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
-
-    /* Get the concrete type of a ANativeWindow.  See below for the list of
-     * possible return values.
-     *
-     * This query should not be used outside the Android framework and will
-     * likely be removed in the near future.
-     */
-    NATIVE_WINDOW_CONCRETE_TYPE,
-};
-
-/* valid operations for the (*perform)() hook */
-enum {
-    NATIVE_WINDOW_SET_USAGE  = 0,
-    NATIVE_WINDOW_CONNECT,
-    NATIVE_WINDOW_DISCONNECT,
-    NATIVE_WINDOW_SET_CROP,
-    NATIVE_WINDOW_SET_BUFFER_COUNT,
-    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
-    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
-};
-
-/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
-enum {
-    NATIVE_WINDOW_API_EGL = 1
-};
-
-/* parameter for NATIVE_WINDOW_SET_BUFFERS_TRANSFORM */
-enum {
-    /* flip source image horizontally */
-    NATIVE_WINDOW_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H ,
-    /* flip source image vertically */
-    NATIVE_WINDOW_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
-    /* rotate source image 90 degrees clock-wise */
-    NATIVE_WINDOW_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
-    /* rotate source image 180 degrees */
-    NATIVE_WINDOW_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
-    /* rotate source image 270 degrees clock-wise */
-    NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
-};
-
-/* values returned by the NATIVE_WINDOW_CONCRETE_TYPE query */
-enum {
-    NATIVE_WINDOW_FRAMEBUFFER,                  // FramebufferNativeWindow
-    NATIVE_WINDOW_SURFACE,                      // Surface
-    NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT,       // SurfaceTextureClient
-};
-
-struct ANativeWindow 
-{
-#ifdef __cplusplus
-    ANativeWindow()
-        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
-    {
-        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
-        common.version = sizeof(ANativeWindow);
-        memset(common.reserved, 0, sizeof(common.reserved));
-    }
-
-    // Implement the methods that sp<ANativeWindow> expects so that it
-    // can be used to automatically refcount ANativeWindow's.
-    void incStrong(const void* id) const {
-        common.incRef(const_cast<android_native_base_t*>(&common));
-    }
-    void decStrong(const void* id) const {
-        common.decRef(const_cast<android_native_base_t*>(&common));
-    }
-#endif
-    
-    struct android_native_base_t common;
-
-    /* flags describing some attributes of this surface or its updater */
-    const uint32_t flags;
-    
-    /* min swap interval supported by this updated */
-    const int   minSwapInterval;
-
-    /* max swap interval supported by this updated */
-    const int   maxSwapInterval;
-
-    /* horizontal and vertical resolution in DPI */
-    const float xdpi;
-    const float ydpi;
-
-    /* Some storage reserved for the OEM's driver. */
-    intptr_t    oem[4];
-        
-
-    /*
-     * Set the swap interval for this surface.
-     * 
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*setSwapInterval)(struct ANativeWindow* window,
-                int interval);
-    
-    /*
-     * hook called by EGL to acquire a buffer. After this call, the buffer
-     * is not locked, so its content cannot be modified.
-     * this call may block if no buffers are available.
-     * 
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*dequeueBuffer)(struct ANativeWindow* window,
-                struct android_native_buffer_t** buffer);
-
-    /*
-     * hook called by EGL to lock a buffer. This MUST be called before modifying
-     * the content of a buffer. The buffer must have been acquired with 
-     * dequeueBuffer first.
-     * 
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*lockBuffer)(struct ANativeWindow* window,
-                struct android_native_buffer_t* buffer);
-   /*
-    * hook called by EGL when modifications to the render buffer are done. 
-    * This unlocks and post the buffer.
-    * 
-    * Buffers MUST be queued in the same order than they were dequeued.
-    * 
-    * Returns 0 on success or -errno on error.
-    */
-    int     (*queueBuffer)(struct ANativeWindow* window,
-                struct android_native_buffer_t* buffer);
-
-    /*
-     * hook used to retrieve information about the native window.
-     * 
-     * Returns 0 on success or -errno on error.
-     */
-    int     (*query)(struct ANativeWindow* window,
-                int what, int* value);
-    
-    /*
-     * hook used to perform various operations on the surface.
-     * (*perform)() is a generic mechanism to add functionality to
-     * ANativeWindow while keeping backward binary compatibility.
-     * 
-     * This hook should not be called directly, instead use the helper functions
-     * defined below.
-     * 
-     *  (*perform)() returns -ENOENT if the 'what' parameter is not supported
-     *  by the surface's implementation.
-     *
-     * The valid operations are:
-     *     NATIVE_WINDOW_SET_USAGE
-     *     NATIVE_WINDOW_CONNECT
-     *     NATIVE_WINDOW_DISCONNECT
-     *     NATIVE_WINDOW_SET_CROP
-     *     NATIVE_WINDOW_SET_BUFFER_COUNT
-     *     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
-     *     NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
-     *  
-     */
-    
-    int     (*perform)(struct ANativeWindow* window,
-                int operation, ... );
-    
-    /*
-     * hook used to cancel a buffer that has been dequeued.
-     * No synchronization is performed between dequeue() and cancel(), so
-     * either external synchronization is needed, or these functions must be
-     * called from the same thread.
-     */
-    int     (*cancelBuffer)(struct ANativeWindow* window,
-                struct android_native_buffer_t* buffer);
-
-
-    void* reserved_proc[2];
-};
-
-// Backwards compatibility...  please switch to ANativeWindow.
-typedef struct ANativeWindow android_native_window_t;
-
-/*
- *  native_window_set_usage(..., usage)
- *  Sets the intended usage flags for the next buffers
- *  acquired with (*lockBuffer)() and on.
- *  By default (if this function is never called), a usage of
- *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
- *  is assumed.
- *  Calling this function will usually cause following buffers to be
- *  reallocated.
- */
-
-static inline int native_window_set_usage(
-        ANativeWindow* window, int usage)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
-}
-
-/*
- * native_window_connect(..., NATIVE_WINDOW_API_EGL)
- * Must be called by EGL when the window is made current.
- * Returns -EINVAL if for some reason the window cannot be connected, which
- * can happen if it's connected to some other API.
- */
-static inline int native_window_connect(
-        ANativeWindow* window, int api)
-{
-    return window->perform(window, NATIVE_WINDOW_CONNECT, api);
-}
-
-/*
- * native_window_disconnect(..., NATIVE_WINDOW_API_EGL)
- * Must be called by EGL when the window is made not current.
- * An error is returned if for instance the window wasn't connected in the
- * first place.
- */
-static inline int native_window_disconnect(
-        ANativeWindow* window, int api)
-{
-    return window->perform(window, NATIVE_WINDOW_DISCONNECT, api);
-}
-
-/*
- * native_window_set_crop(..., crop)
- * Sets which region of the next queued buffers needs to be considered.
- * A buffer's crop region is scaled to match the surface's size.
- *
- * The specified crop region applies to all buffers queued after it is called.
- *
- * if 'crop' is NULL, subsequently queued buffers won't be cropped.
- *
- * An error is returned if for instance the crop region is invalid,
- * out of the buffer's bound or if the window is invalid.
- */
-static inline int native_window_set_crop(
-        ANativeWindow* window,
-        android_native_rect_t const * crop)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
-}
-
-/*
- * native_window_set_buffer_count(..., count)
- * Sets the number of buffers associated with this native window.
- */
-static inline int native_window_set_buffer_count(
-        ANativeWindow* window,
-        size_t bufferCount)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
-}
-
-/*
- * native_window_set_buffers_geometry(..., int w, int h, int format)
- * All buffers dequeued after this call will have the geometry specified.
- * In particular, all buffers will have a fixed-size, independent form the
- * native-window size. They will be appropriately scaled to the window-size
- * upon composition.
- *
- * If all parameters are 0, the normal behavior is restored. That is,
- * dequeued buffers following this call will be sized to the window's size.
- *
- * Calling this function will reset the window crop to a NULL value, which
- * disables cropping of the buffers.
- */
-static inline int native_window_set_buffers_geometry(
-        ANativeWindow* window,
-        int w, int h, int format)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
-            w, h, format);
-}
-
-/*
- * native_window_set_buffers_transform(..., int transform)
- * All buffers queued after this call will be displayed transformed according
- * to the transform parameter specified.
- */
-static inline int native_window_set_buffers_transform(
-        ANativeWindow* window,
-        int transform)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
-            transform);
-}
-
 // ---------------------------------------------------------------------------
 
 /* FIXME: this is legacy for pixmaps */
@@ -411,13 +46,6 @@
 /*****************************************************************************/
 
 #ifdef __cplusplus
-}
-#endif
-
-
-/*****************************************************************************/
-
-#ifdef __cplusplus
 
 #include <utils/RefBase.h>
 
diff --git a/include/utils/BackupHelpers.h b/include/utils/BackupHelpers.h
index b1f5045..1bb04a7 100644
--- a/include/utils/BackupHelpers.h
+++ b/include/utils/BackupHelpers.h
@@ -70,6 +70,14 @@
     ~BackupDataWriter();
 
     status_t WriteEntityHeader(const String8& key, size_t dataSize);
+
+    /* Note: WriteEntityData will write arbitrary data into the file without
+     * validation or a previously-supplied header.  The full backup implementation
+     * uses it this way to generate a controlled binary stream that is not
+     * entity-structured.  If the implementation here is changed, either this
+     * use case must remain valid, or the full backup implementation should be
+     * adjusted to use some other appropriate mechanism.
+     */
     status_t WriteEntityData(const void* data, size_t size);
 
     void SetKeyPrefix(const String8& keyPrefix);
@@ -103,7 +111,7 @@
 
     bool HasEntities();
     status_t ReadEntityHeader(String8* key, size_t* dataSize);
-    status_t SkipEntityData(); // must be called with the pointer at the begining of the data.
+    status_t SkipEntityData(); // must be called with the pointer at the beginning of the data.
     ssize_t ReadEntityData(void* data, size_t size);
 
 private:
@@ -126,6 +134,9 @@
 int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
         char const* const* files, char const* const *keys, int fileCount);
 
+int write_tarfile(const String8& packageName, const String8& domain,
+        const String8& rootPath, const String8& filePath, BackupDataWriter* outputStream);
+
 class RestoreHelperBase
 {
 public:
diff --git a/include/utils/BitSet.h b/include/utils/BitSet.h
index f5dbcd9..de748b5 100644
--- a/include/utils/BitSet.h
+++ b/include/utils/BitSet.h
@@ -61,6 +61,16 @@
     // Result is undefined if all bits are marked.
     inline uint32_t firstUnmarkedBit() const { return __builtin_clz(~ value); }
 
+    // Finds the last marked bit in the set.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t lastMarkedBit() const { return 31 - __builtin_ctz(value); }
+
+    // Gets the index of the specified bit in the set, which is the number of
+    // marked bits that appear before the specified bit.
+    inline uint32_t getIndexOfBit(uint32_t n) const {
+        return __builtin_popcount(value & ~(0xffffffffUL >> n));
+    }
+
     inline bool operator== (const BitSet32& other) const { return value == other.value; }
     inline bool operator!= (const BitSet32& other) const { return value != other.value; }
 };
diff --git a/include/utils/GenerationCache.h b/include/utils/GenerationCache.h
new file mode 100644
index 0000000..bb9ddd6
--- /dev/null
+++ b/include/utils/GenerationCache.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UTILS_GENERATION_CACHE_H
+#define ANDROID_UTILS_GENERATION_CACHE_H
+
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+/**
+ * GenerationCache callback used when an item is removed
+ */
+template<typename EntryKey, typename EntryValue>
+class OnEntryRemoved {
+public:
+    virtual ~OnEntryRemoved() { };
+    virtual void operator()(EntryKey& key, EntryValue& value) = 0;
+}; // class OnEntryRemoved
+
+template<typename EntryKey, typename EntryValue>
+struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
+    Entry() { }
+    Entry(const Entry<EntryKey, EntryValue>& e):
+            key(e.key), value(e.value), parent(e.parent), child(e.child) { }
+    Entry(sp<Entry<EntryKey, EntryValue> > e):
+            key(e->key), value(e->value), parent(e->parent), child(e->child) { }
+
+    EntryKey key;
+    EntryValue value;
+
+    sp<Entry<EntryKey, EntryValue> > parent;
+    sp<Entry<EntryKey, EntryValue> > child;
+}; // struct Entry
+
+/**
+ * A LRU type cache
+ */
+template<typename K, typename V>
+class GenerationCache {
+public:
+    GenerationCache(uint32_t maxCapacity);
+    virtual ~GenerationCache();
+
+    enum Capacity {
+        kUnlimitedCapacity,
+    };
+
+    void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
+
+    void clear();
+
+    bool contains(K key) const;
+    V get(K key);
+    K getKeyAt(uint32_t index) const;
+    bool put(K key, V value);
+    V remove(K key);
+    V removeOldest();
+    V getValueAt(uint32_t index) const;
+
+    uint32_t size() const;
+
+    void addToCache(sp<Entry<K, V> > entry, K key, V value);
+    void attachToCache(sp<Entry<K, V> > entry);
+    void detachFromCache(sp<Entry<K, V> > entry);
+
+    V removeAt(ssize_t index);
+
+private:
+    KeyedVector<K, sp<Entry<K, V> > > mCache;
+    uint32_t mMaxCapacity;
+
+    OnEntryRemoved<K, V>* mListener;
+
+    sp<Entry<K, V> > mOldest;
+    sp<Entry<K, V> > mYoungest;
+}; // class GenerationCache
+
+template<typename K, typename V>
+GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity),
+    mListener(NULL) {
+};
+
+template<typename K, typename V>
+GenerationCache<K, V>::~GenerationCache() {
+    clear();
+};
+
+template<typename K, typename V>
+uint32_t GenerationCache<K, V>::size() const {
+    return mCache.size();
+}
+
+/**
+ * Should be set by the user of the Cache so that the callback is called whenever an item is
+ * removed from the cache
+ */
+template<typename K, typename V>
+void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
+    mListener = listener;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::clear() {
+    if (mListener) {
+        for (uint32_t i = 0; i < mCache.size(); i++) {
+            sp<Entry<K, V> > entry = mCache.valueAt(i);
+            if (mListener) {
+                (*mListener)(entry->key, entry->value);
+            }
+        }
+    }
+    mCache.clear();
+    mYoungest.clear();
+    mOldest.clear();
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::contains(K key) const {
+    return mCache.indexOfKey(key) >= 0;
+}
+
+template<typename K, typename V>
+K GenerationCache<K, V>::getKeyAt(uint32_t index) const {
+    return mCache.keyAt(index);
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::getValueAt(uint32_t index) const {
+    return mCache.valueAt(index)->value;
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::get(K key) {
+    ssize_t index = mCache.indexOfKey(key);
+    if (index >= 0) {
+        sp<Entry<K, V> > entry = mCache.valueAt(index);
+        if (entry.get()) {
+            detachFromCache(entry);
+            attachToCache(entry);
+            return entry->value;
+        }
+    }
+
+    return NULL;
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::put(K key, V value) {
+    if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
+        removeOldest();
+    }
+
+    ssize_t index = mCache.indexOfKey(key);
+    if (index < 0) {
+        sp<Entry<K, V> > entry = new Entry<K, V>;
+        addToCache(entry, key, value);
+        return true;
+    }
+
+    return false;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) {
+    entry->key = key;
+    entry->value = value;
+    mCache.add(key, entry);
+    attachToCache(entry);
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::remove(K key) {
+    ssize_t index = mCache.indexOfKey(key);
+    if (index >= 0) {
+        return removeAt(index);
+    }
+
+    return NULL;
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::removeAt(ssize_t index) {
+    sp<Entry<K, V> > entry = mCache.valueAt(index);
+    if (mListener) {
+        (*mListener)(entry->key, entry->value);
+    }
+    mCache.removeItemsAt(index, 1);
+    detachFromCache(entry);
+
+    return entry->value;
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::removeOldest() {
+    if (mOldest.get()) {
+        ssize_t index = mCache.indexOfKey(mOldest->key);
+        if (index >= 0) {
+            return removeAt(index);
+        }
+    }
+
+    return NULL;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) {
+    if (!mYoungest.get()) {
+        mYoungest = mOldest = entry;
+    } else {
+        entry->parent = mYoungest;
+        mYoungest->child = entry;
+        mYoungest = entry;
+    }
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) {
+    if (entry->parent.get()) {
+        entry->parent->child = entry->child;
+    }
+
+    if (entry->child.get()) {
+        entry->child->parent = entry->parent;
+    }
+
+    if (mOldest == entry) {
+        mOldest = entry->child;
+    }
+
+    if (mYoungest == entry) {
+        mYoungest = entry->parent;
+    }
+
+    entry->parent.clear();
+    entry->child.clear();
+}
+
+}; // namespace android
+
+#endif // ANDROID_UTILS_GENERATION_CACHE_H
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index f355087..4126225 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -51,7 +51,6 @@
 }
 
 // ---------------------------------------------------------------------------
-
 class ReferenceMover;
 class ReferenceConverterBase {
 public:
@@ -120,7 +119,14 @@
 protected:
                             RefBase();
     virtual                 ~RefBase();
-    
+
+    // called when the last reference goes away. this is responsible for
+    // calling the destructor. The default implementation just does
+    // "delete this;".
+    // Make sure to never acquire a strong reference from this function. The
+    // same restrictions than for destructors apply.
+    virtual void            destroy() const;
+
     //! Flags for extendObjectLifetime()
     enum {
         OBJECT_LIFETIME_WEAK    = 0x0001,
diff --git a/include/utils/Timers.h b/include/utils/Timers.h
index 9a9e07c..8b4d322 100644
--- a/include/utils/Timers.h
+++ b/include/utils/Timers.h
@@ -88,6 +88,16 @@
 nsecs_t systemTime(int clock);
 #endif // def __cplusplus
 
+/**
+ * Returns the number of milliseconds to wait between the reference time and the timeout time.
+ * If the timeout is in the past relative to the reference time, returns 0.
+ * If the timeout is more than INT_MAX milliseconds in the future relative to the reference time,
+ * such as when timeoutTime == LLONG_MAX, returns -1 to indicate an infinite timeout delay.
+ * Otherwise, returns the difference between the reference time and timeout time
+ * rounded up to the next millisecond.
+ */
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index 6fd307f..f1e87e6 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -165,6 +165,26 @@
      // for debugging only
      inline size_t getItemSize() const { return itemSize(); }
 
+
+     /*
+      * these inlines add some level of compatibility with STL. eventually
+      * we should probably turn things around.
+      */
+     typedef TYPE* iterator;
+     typedef TYPE const* const_iterator;
+
+     inline iterator begin() { return editArray(); }
+     inline iterator end()   { return editArray() + size(); }
+     inline const_iterator begin() const { return array(); }
+     inline const_iterator end() const   { return array() + size(); }
+     inline void reserve(size_t n) { setCapacity(n); }
+     inline bool empty() const{ return isEmpty(); }
+     inline void push_back(const TYPE& item)  { insertAt(item, size()); }
+     inline void push_front(const TYPE& item) { insertAt(item, 0); }
+     inline iterator erase(iterator pos) {
+         return begin() + removeItemsAt(pos-array());
+     }
+
 protected:
     virtual void    do_construct(void* storage, size_t num) const;
     virtual void    do_destroy(void* storage, size_t num) const;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 95cfddf..392193b 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -851,6 +851,9 @@
     tr.target.handle = handle;
     tr.code = code;
     tr.flags = binderFlags;
+    tr.cookie = 0;
+    tr.sender_pid = 0;
+    tr.sender_euid = 0;
     
     const status_t err = data.errorCheck();
     if (err == NO_ERROR) {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index d57f2c9..a0fc4d0 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -338,7 +338,7 @@
 
 status_t Parcel::setDataCapacity(size_t size)
 {
-    if (size > mDataSize) return continueWrite(size);
+    if (size > mDataCapacity) return continueWrite(size);
     return NO_ERROR;
 }
 
@@ -353,12 +353,12 @@
     return err;
 }
 
-status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len)
+status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
 {
     const sp<ProcessState> proc(ProcessState::self());
     status_t err;
-    uint8_t *data = parcel->mData;
-    size_t *objects = parcel->mObjects;
+    const uint8_t *data = parcel->mData;
+    const size_t *objects = parcel->mObjects;
     size_t size = parcel->mObjectsSize;
     int startPos = mDataPos;
     int firstIndex = -1, lastIndex = -2;
@@ -386,10 +386,12 @@
     }
     int numObjects = lastIndex - firstIndex + 1;
 
-    // grow data
-    err = growData(len);
-    if (err != NO_ERROR) {
-        return err;
+    if ((mDataSize+len) > mDataCapacity) {
+        // grow data
+        err = growData(len);
+        if (err != NO_ERROR) {
+            return err;
+        }
     }
 
     // append data
@@ -1384,8 +1386,10 @@
                 return NO_MEMORY;
             }
         } else {
-            mDataSize = desired;
-            LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize);
+            if (mDataSize > desired) {
+                mDataSize = desired;
+                LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize);
+            }
             if (mDataPos > desired) {
                 mDataPos = desired;
                 LOGV("continueWrite Setting data pos of %p to %d\n", this, mDataPos);
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index d1a6af1..b5737ff 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -10,7 +10,15 @@
 	SensorEventQueue.cpp \
 	SensorManager.cpp \
 	SurfaceTexture.cpp \
-	SurfaceTextureClient.cpp
+	SurfaceTextureClient.cpp \
+	ISurfaceComposer.cpp \
+	ISurface.cpp \
+	ISurfaceComposerClient.cpp \
+	IGraphicBufferAlloc.cpp \
+	LayerState.cpp \
+	SharedBufferStack.cpp \
+	Surface.cpp \
+	SurfaceComposerClient.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
@@ -21,7 +29,6 @@
 	libui \
 	libEGL \
 	libGLESv2 \
-	libsurfaceflinger_client
 
 
 LOCAL_MODULE:= libgui
@@ -31,3 +38,7 @@
 endif
 
 include $(BUILD_SHARED_LIBRARY)
+
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
similarity index 71%
rename from libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
rename to libs/gui/IGraphicBufferAlloc.cpp
index e05da72..0cd51da 100644
--- a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -32,7 +32,6 @@
 
 enum {
     CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
-    FREE_ALL_GRAPHIC_BUFFERS_EXCEPT,
 };
 
 class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
@@ -46,8 +45,7 @@
     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
             PixelFormat format, uint32_t usage) {
         Parcel data, reply;
-        data.writeInterfaceToken(
-                IGraphicBufferAlloc::getInterfaceDescriptor());
+        data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
         data.writeInt32(w);
         data.writeInt32(h);
         data.writeInt32(format);
@@ -58,17 +56,12 @@
         if (nonNull) {
             graphicBuffer = new GraphicBuffer();
             reply.read(*graphicBuffer);
+            // reply.readStrongBinder();
+            // here we don't even have to read the BufferReference from
+            // the parcel, it'll die with the parcel.
         }
         return graphicBuffer;
     }
-
-    virtual void freeAllGraphicBuffersExcept(int bufIdx) {
-        Parcel data, reply;
-        data.writeInterfaceToken(
-                IGraphicBufferAlloc::getInterfaceDescriptor());
-        data.writeInt32(bufIdx);
-        remote()->transact(FREE_ALL_GRAPHIC_BUFFERS_EXCEPT, data, &reply);
-    }
 };
 
 IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
@@ -80,6 +73,17 @@
 {
     // codes that don't require permission check
 
+    /* BufferReference just keeps a strong reference to a
+     * GraphicBuffer until it is destroyed (that is, until
+     * no local or remote process have a reference to it).
+     */
+    class BufferReference : public BBinder {
+        sp<GraphicBuffer> buffer;
+    public:
+        BufferReference(const sp<GraphicBuffer>& buffer) : buffer(buffer) { }
+    };
+
+
     switch(code) {
         case CREATE_GRAPHIC_BUFFER: {
             CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
@@ -91,15 +95,16 @@
             reply->writeInt32(result != 0);
             if (result != 0) {
                 reply->write(*result);
+                // We add a BufferReference to this parcel to make sure the
+                // buffer stays alive until the GraphicBuffer object on
+                // the other side has been created.
+                // This is needed so that the buffer handle can be
+                // registered before the buffer is destroyed on implementations
+                // that do not use file-descriptors to track their buffers.
+                reply->writeStrongBinder( new BufferReference(result) );
             }
             return NO_ERROR;
         } break;
-        case FREE_ALL_GRAPHIC_BUFFERS_EXCEPT: {
-            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
-            int bufIdx = data.readInt32();
-            freeAllGraphicBuffersExcept(bufIdx);
-            return NO_ERROR;
-        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/surfaceflinger_client/ISurface.cpp b/libs/gui/ISurface.cpp
similarity index 100%
rename from libs/surfaceflinger_client/ISurface.cpp
rename to libs/gui/ISurface.cpp
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
similarity index 100%
rename from libs/surfaceflinger_client/ISurfaceComposer.cpp
rename to libs/gui/ISurfaceComposer.cpp
diff --git a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
similarity index 97%
rename from libs/surfaceflinger_client/ISurfaceComposerClient.cpp
rename to libs/gui/ISurfaceComposerClient.cpp
index 7730eb1..ea38e08 100644
--- a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -83,7 +83,6 @@
     }
 
     virtual sp<ISurface> createSurface( surface_data_t* params,
-                                        int pid,
                                         const String8& name,
                                         DisplayID display,
                                         uint32_t w,
@@ -93,7 +92,6 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
-        data.writeInt32(pid);
         data.writeString8(name);
         data.writeInt32(display);
         data.writeInt32(w);
@@ -172,14 +170,13 @@
         case CREATE_SURFACE: {
             CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
             surface_data_t params;
-            int32_t pid = data.readInt32();
             String8 name = data.readString8();
             DisplayID display = data.readInt32();
             uint32_t w = data.readInt32();
             uint32_t h = data.readInt32();
             PixelFormat format = data.readInt32();
             uint32_t flags = data.readInt32();
-            sp<ISurface> s = createSurface(&params, pid, name, display, w, h,
+            sp<ISurface> s = createSurface(&params, name, display, w, h,
                     format, flags);
             params.writeToParcel(reply);
             reply->writeStrongBinder(s->asBinder());
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index d661fd5..16e3780 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -39,6 +39,8 @@
     SET_CROP,
     SET_TRANSFORM,
     GET_ALLOCATOR,
+    QUERY,
+    SET_SYNCHRONOUS_MODE,
 };
 
 
@@ -50,15 +52,10 @@
     {
     }
 
-    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
-            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
         data.writeInt32(bufferIdx);
-        data.writeInt32(w);
-        data.writeInt32(h);
-        data.writeInt32(format);
-        data.writeInt32(usage);
         remote()->transact(REQUEST_BUFFER, data, &reply);
         sp<GraphicBuffer> buffer;
         bool nonNull = reply.readInt32();
@@ -79,19 +76,25 @@
         return err;
     }
 
-    virtual status_t dequeueBuffer(int *buf) {
+    virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
+        data.writeInt32(usage);
         remote()->transact(DEQUEUE_BUFFER, data, &reply);
         *buf = reply.readInt32();
         int result = reply.readInt32();
         return result;
     }
 
-    virtual status_t queueBuffer(int buf) {
+    virtual status_t queueBuffer(int buf, int64_t timestamp) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
         data.writeInt32(buf);
+        data.writeInt64(timestamp);
         remote()->transact(QUEUE_BUFFER, data, &reply);
         status_t result = reply.readInt32();
         return result;
@@ -131,6 +134,27 @@
         remote()->transact(GET_ALLOCATOR, data, &reply);
         return reply.readStrongBinder();
     }
+
+    virtual int query(int what, int* value) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(what);
+        remote()->transact(QUERY, data, &reply);
+        value[0] = reply.readInt32();
+        status_t result = reply.readInt32();
+        return result;
+    }
+
+    virtual status_t setSynchronousMode(bool enabled) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(enabled);
+        remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
+
+
 };
 
 IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
@@ -144,12 +168,7 @@
         case REQUEST_BUFFER: {
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
             int bufferIdx   = data.readInt32();
-            uint32_t w      = data.readInt32();
-            uint32_t h      = data.readInt32();
-            uint32_t format = data.readInt32();
-            uint32_t usage  = data.readInt32();
-            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format,
-                    usage));
+            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx));
             reply->writeInt32(buffer != 0);
             if (buffer != 0) {
                 reply->write(*buffer);
@@ -165,8 +184,12 @@
         } break;
         case DEQUEUE_BUFFER: {
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            uint32_t w      = data.readInt32();
+            uint32_t h      = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t usage  = data.readInt32();
             int buf;
-            int result = dequeueBuffer(&buf);
+            int result = dequeueBuffer(&buf, w, h, format, usage);
             reply->writeInt32(buf);
             reply->writeInt32(result);
             return NO_ERROR;
@@ -174,7 +197,8 @@
         case QUEUE_BUFFER: {
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
             int buf = data.readInt32();
-            status_t result = queueBuffer(buf);
+            int64_t timestamp = data.readInt64();
+            status_t result = queueBuffer(buf, timestamp);
             reply->writeInt32(result);
             return NO_ERROR;
         } break;
@@ -196,7 +220,6 @@
             return NO_ERROR;
         } break;
         case SET_TRANSFORM: {
-            Rect reg;
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
             uint32_t transform = data.readInt32();
             status_t result = setTransform(transform);
@@ -209,6 +232,22 @@
             reply->writeStrongBinder(result);
             return NO_ERROR;
         } break;
+        case QUERY: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int value;
+            int what = data.readInt32();
+            int res = query(what, &value);
+            reply->writeInt32(value);
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+        case SET_SYNCHRONOUS_MODE: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            bool enabled = data.readInt32();
+            status_t res = setSynchronousMode(enabled);
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/surfaceflinger_client/LayerState.cpp b/libs/gui/LayerState.cpp
similarity index 100%
rename from libs/surfaceflinger_client/LayerState.cpp
rename to libs/gui/LayerState.cpp
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/gui/SharedBufferStack.cpp
similarity index 100%
rename from libs/surfaceflinger_client/SharedBufferStack.cpp
rename to libs/gui/SharedBufferStack.cpp
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/gui/Surface.cpp
similarity index 96%
rename from libs/surfaceflinger_client/Surface.cpp
rename to libs/gui/Surface.cpp
index 21d509a..0c5767b 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -502,8 +502,8 @@
     return NO_ERROR;
 }
 
-sp<ISurface> Surface::getISurface() const {
-    return mSurface;
+sp<IBinder> Surface::asBinder() const {
+    return mSurface!=0 ? mSurface->asBinder() : 0;
 }
 
 // ----------------------------------------------------------------------------
@@ -513,32 +513,32 @@
 }
 
 int Surface::dequeueBuffer(ANativeWindow* window, 
-        android_native_buffer_t** buffer) {
+        ANativeWindowBuffer** buffer) {
     Surface* self = getSelf(window);
     return self->dequeueBuffer(buffer);
 }
 
 int Surface::cancelBuffer(ANativeWindow* window,
-        android_native_buffer_t* buffer) {
+        ANativeWindowBuffer* buffer) {
     Surface* self = getSelf(window);
     return self->cancelBuffer(buffer);
 }
 
 int Surface::lockBuffer(ANativeWindow* window, 
-        android_native_buffer_t* buffer) {
+        ANativeWindowBuffer* buffer) {
     Surface* self = getSelf(window);
     return self->lockBuffer(buffer);
 }
 
 int Surface::queueBuffer(ANativeWindow* window, 
-        android_native_buffer_t* buffer) {
+        ANativeWindowBuffer* buffer) {
     Surface* self = getSelf(window);
     return self->queueBuffer(buffer);
 }
 
-int Surface::query(ANativeWindow* window, 
+int Surface::query(const ANativeWindow* window,
         int what, int* value) {
-    Surface* self = getSelf(window);
+    const Surface* self = getSelf(window);
     return self->query(what, value);
 }
 
@@ -570,7 +570,7 @@
     return newNeewBuffer;
 }
 
-int Surface::dequeueBuffer(android_native_buffer_t** buffer)
+int Surface::dequeueBuffer(ANativeWindowBuffer** buffer)
 {
     status_t err = validate();
     if (err != NO_ERROR)
@@ -624,7 +624,7 @@
     return err;
 }
 
-int Surface::cancelBuffer(android_native_buffer_t* buffer)
+int Surface::cancelBuffer(ANativeWindowBuffer* buffer)
 {
     status_t err = validate(true);
     switch (err) {
@@ -651,7 +651,7 @@
 }
 
 
-int Surface::lockBuffer(android_native_buffer_t* buffer)
+int Surface::lockBuffer(ANativeWindowBuffer* buffer)
 {
     status_t err = validate();
     if (err != NO_ERROR)
@@ -670,7 +670,7 @@
     return err;
 }
 
-int Surface::queueBuffer(android_native_buffer_t* buffer)
+int Surface::queueBuffer(ANativeWindowBuffer* buffer)
 {
     status_t err = validate();
     if (err != NO_ERROR)
@@ -697,7 +697,7 @@
     return err;
 }
 
-int Surface::query(int what, int* value)
+int Surface::query(int what, int* value) const
 {
     switch (what) {
     case NATIVE_WINDOW_WIDTH:
@@ -753,6 +753,9 @@
     case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
         res = dispatch_set_buffers_transform( args );
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+        res = dispatch_set_buffers_timestamp( args );
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -792,6 +795,11 @@
     return setBuffersTransform(transform);
 }
 
+int Surface::dispatch_set_buffers_timestamp(va_list args) {
+    int64_t timestamp = va_arg(args, int64_t);
+    return setBuffersTimestamp(timestamp);
+}
+
 void Surface::setUsage(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mSurfaceLock);
@@ -910,6 +918,13 @@
     return NO_ERROR;
 }
 
+int Surface::setBuffersTimestamp(int64_t timestamp)
+{
+    // Surface doesn't really have anything meaningful to do with timestamps
+    // so they'll just be dropped here.
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 
 int Surface::getConnectedApi() const
@@ -954,7 +969,7 @@
     // we're intending to do software rendering from this point
     setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
 
-    android_native_buffer_t* out;
+    ANativeWindowBuffer* out;
     status_t err = dequeueBuffer(&out);
     LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
     if (err == NO_ERROR) {
@@ -1048,7 +1063,7 @@
     if (idx < 0) {
         // The buffer doesn't have an index set.  See if the handle the same as
         // one of the buffers for which we do know the index.  This can happen
-        // e.g. if GraphicBuffer is used to wrap an android_native_buffer_t that
+        // e.g. if GraphicBuffer is used to wrap an ANativeWindowBuffer that
         // was dequeued from an ANativeWindow.
         for (size_t i = 0; i < mBuffers.size(); i++) {
             if (mBuffers[i] != 0 && buffer->handle == mBuffers[i]->handle) {
diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
similarity index 98%
rename from libs/surfaceflinger_client/SurfaceComposerClient.cpp
rename to libs/gui/SurfaceComposerClient.cpp
index d336724..a1ff2c1 100644
--- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -273,7 +273,6 @@
 }
 
 sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        int pid,
         DisplayID display,
         uint32_t w,
         uint32_t h,
@@ -286,12 +285,11 @@
     snprintf(buffer, SIZE, "<pid_%d>", getpid());
     name.append(buffer);
 
-    return SurfaceComposerClient::createSurface(pid, name, display,
+    return SurfaceComposerClient::createSurface(name, display,
             w, h, format, flags);
 }
 
 sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        int pid,
         const String8& name,
         DisplayID display,
         uint32_t w,
@@ -302,7 +300,7 @@
     sp<SurfaceControl> result;
     if (mStatus == NO_ERROR) {
         ISurfaceComposerClient::surface_data_t data;
-        sp<ISurface> surface = mClient->createSurface(&data, pid, name,
+        sp<ISurface> surface = mClient->createSurface(&data, name,
                 display, w, h, format, flags);
         if (surface != 0) {
             result = new SurfaceControl(this, surface, data, w, h, format, flags);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 5c6d71b..b08a5a8 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -27,11 +27,14 @@
 
 #include <gui/SurfaceTexture.h>
 
+#include <hardware/hardware.h>
+
 #include <surfaceflinger/ISurfaceComposer.h>
 #include <surfaceflinger/SurfaceComposerClient.h>
 #include <surfaceflinger/IGraphicBufferAlloc.h>
 
 #include <utils/Log.h>
+#include <utils/String8.h>
 
 namespace android {
 
@@ -76,17 +79,23 @@
 static void mtxMul(float out[16], const float a[16], const float b[16]);
 
 SurfaceTexture::SurfaceTexture(GLuint tex) :
-    mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
-    mCurrentTransform(0), mLastQueued(INVALID_BUFFER_SLOT),
-    mLastQueuedTransform(0), mNextTransform(0), mTexName(tex) {
+    mDefaultWidth(1),
+    mDefaultHeight(1),
+    mPixelFormat(PIXEL_FORMAT_RGBA_8888),
+    mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+    mClientBufferCount(0),
+    mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+    mCurrentTexture(INVALID_BUFFER_SLOT),
+    mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
+    mCurrentTransform(0),
+    mCurrentTimestamp(0),
+    mNextTransform(0),
+    mTexName(tex),
+    mSynchronousMode(false) {
     LOGV("SurfaceTexture::SurfaceTexture");
-    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
-        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
-        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
-        mSlots[i].mOwnedByClient = false;
-    }
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
+    mNextCrop.makeInvalid();
 }
 
 SurfaceTexture::~SurfaceTexture() {
@@ -94,23 +103,94 @@
     freeAllBuffers();
 }
 
-status_t SurfaceTexture::setBufferCount(int bufferCount) {
-    LOGV("SurfaceTexture::setBufferCount");
-
-    if (bufferCount < MIN_BUFFER_SLOTS) {
+status_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) {
+    if (bufferCount > NUM_BUFFER_SLOTS)
         return BAD_VALUE;
-    }
 
-    Mutex::Autolock lock(mMutex);
-    freeAllBuffers();
-    mBufferCount = bufferCount;
-    mCurrentTexture = INVALID_BUFFER_SLOT;
-    mLastQueued = INVALID_BUFFER_SLOT;
+    // special-case, nothing to do
+    if (bufferCount == mBufferCount)
+        return OK;
+
+    if (!mClientBufferCount &&
+        bufferCount >= mBufferCount) {
+        // easy, we just have more buffers
+        mBufferCount = bufferCount;
+        mServerBufferCount = bufferCount;
+        mDequeueCondition.signal();
+    } else {
+        // we're here because we're either
+        // - reducing the number of available buffers
+        // - or there is a client-buffer-count in effect
+
+        // less than 2 buffers is never allowed
+        if (bufferCount < 2)
+            return BAD_VALUE;
+
+        // when there is non client-buffer-count in effect, the client is not
+        // allowed to dequeue more than one buffer at a time,
+        // so the next time they dequeue a buffer, we know that they don't
+        // own one. the actual resizing will happen during the next
+        // dequeueBuffer.
+
+        mServerBufferCount = bufferCount;
+    }
     return OK;
 }
 
-sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
-        uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
+    Mutex::Autolock lock(mMutex);
+    return setBufferCountServerLocked(bufferCount);
+}
+
+status_t SurfaceTexture::setBufferCount(int bufferCount) {
+    LOGV("SurfaceTexture::setBufferCount");
+    Mutex::Autolock lock(mMutex);
+
+    // Error out if the user has dequeued buffers
+    for (int i=0 ; i<mBufferCount ; i++) {
+        if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
+            LOGE("setBufferCount: client owns some buffers");
+            return -EINVAL;
+        }
+    }
+
+    if (bufferCount == 0) {
+        const int minBufferSlots = mSynchronousMode ?
+                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+        mClientBufferCount = 0;
+        bufferCount = (mServerBufferCount >= minBufferSlots) ?
+                mServerBufferCount : minBufferSlots;
+        return setBufferCountServerLocked(bufferCount);
+    }
+
+    // We don't allow the client to set a buffer-count less than
+    // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it.
+    if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) {
+        return BAD_VALUE;
+    }
+
+    // here we're guaranteed that the client doesn't have dequeued buffers
+    // and will release all of its buffer references.
+    freeAllBuffers();
+    mBufferCount = bufferCount;
+    mClientBufferCount = bufferCount;
+    mCurrentTexture = INVALID_BUFFER_SLOT;
+    mQueue.clear();
+    mDequeueCondition.signal();
+    return OK;
+}
+
+status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
+{
+    Mutex::Autolock lock(mMutex);
+    if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
+        mDefaultWidth = w;
+        mDefaultHeight = h;
+    }
+    return OK;
+}
+
+sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) {
     LOGV("SurfaceTexture::requestBuffer");
     Mutex::Autolock lock(mMutex);
     if (buf < 0 || mBufferCount <= buf) {
@@ -118,62 +198,246 @@
                 mBufferCount, buf);
         return 0;
     }
-    usage |= GraphicBuffer::USAGE_HW_TEXTURE;
-    sp<GraphicBuffer> graphicBuffer(
-            mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
-    if (graphicBuffer == 0) {
-        LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
-    } else {
+    mSlots[buf].mRequestBufferCalled = true;
+    return mSlots[buf].mGraphicBuffer;
+}
+
+status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
+        uint32_t format, uint32_t usage) {
+    LOGV("SurfaceTexture::dequeueBuffer");
+
+    if ((w && !h) || (!w & h)) {
+        LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+
+    status_t returnFlags(OK);
+
+    int found, foundSync;
+    int dequeuedCount = 0;
+    bool tryAgain = true;
+    while (tryAgain) {
+        // We need to wait for the FIFO to drain if the number of buffer
+        // needs to change.
+        //
+        // The condition "number of buffer needs to change" is true if
+        // - the client doesn't care about how many buffers there are
+        // - AND the actual number of buffer is different from what was
+        //   set in the last setBufferCountServer()
+        //                         - OR -
+        //   setBufferCountServer() was set to a value incompatible with
+        //   the synchronization mode (for instance because the sync mode
+        //   changed since)
+        //
+        // As long as this condition is true AND the FIFO is not empty, we
+        // wait on mDequeueCondition.
+
+        int minBufferCountNeeded = mSynchronousMode ?
+                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+
+        if (!mClientBufferCount &&
+                ((mServerBufferCount != mBufferCount) ||
+                        (mServerBufferCount < minBufferCountNeeded))) {
+            // wait for the FIFO to drain
+            while (!mQueue.isEmpty()) {
+                mDequeueCondition.wait(mMutex);
+            }
+            minBufferCountNeeded = mSynchronousMode ?
+                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+        }
+
+
+        if (!mClientBufferCount &&
+                ((mServerBufferCount != mBufferCount) ||
+                        (mServerBufferCount < minBufferCountNeeded))) {
+            // here we're guaranteed that mQueue is empty
+            freeAllBuffers();
+            mBufferCount = mServerBufferCount;
+            if (mBufferCount < minBufferCountNeeded)
+                mBufferCount = minBufferCountNeeded;
+            mCurrentTexture = INVALID_BUFFER_SLOT;
+            returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
+        }
+
+        // look for a free buffer to give to the client
+        found = INVALID_BUFFER_SLOT;
+        foundSync = INVALID_BUFFER_SLOT;
+        dequeuedCount = 0;
+        for (int i = 0; i < mBufferCount; i++) {
+            const int state = mSlots[i].mBufferState;
+            if (state == BufferSlot::DEQUEUED) {
+                dequeuedCount++;
+            }
+            if (state == BufferSlot::FREE || i == mCurrentTexture) {
+                foundSync = i;
+                if (i != mCurrentTexture) {
+                    found = i;
+                    break;
+                }
+            }
+        }
+
+        // clients are not allowed to dequeue more than one buffer
+        // if they didn't set a buffer count.
+        if (!mClientBufferCount && dequeuedCount) {
+            return -EINVAL;
+        }
+
+        // make sure the client is not trying to dequeue more buffers
+        // than allowed.
+        const int avail = mBufferCount - (dequeuedCount+1);
+        if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
+            LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
+                    MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
+                    dequeuedCount);
+            // TODO: Enable this error report after we fix issue 4435022
+            // return -EBUSY;
+        }
+
+        // we're in synchronous mode and didn't find a buffer, we need to wait
+        // for for some buffers to be consumed
+        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
+        if (tryAgain) {
+            mDequeueCondition.wait(mMutex);
+        }
+    }
+
+    if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
+        // foundSync guaranteed to be != INVALID_BUFFER_SLOT
+        found = foundSync;
+    }
+
+    if (found == INVALID_BUFFER_SLOT) {
+        return -EBUSY;
+    }
+
+    const int buf = found;
+    *outBuf = found;
+
+    const bool useDefaultSize = !w && !h;
+    if (useDefaultSize) {
+        // use the default size
+        w = mDefaultWidth;
+        h = mDefaultHeight;
+    }
+
+    const bool updateFormat = (format != 0);
+    if (!updateFormat) {
+        // keep the current (or default) format
+        format = mPixelFormat;
+    }
+
+    // buffer is now in DEQUEUED (but can also be current at the same time,
+    // if we're in synchronous mode)
+    mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
+
+    const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
+    if ((buffer == NULL) ||
+        (uint32_t(buffer->width)  != w) ||
+        (uint32_t(buffer->height) != h) ||
+        (uint32_t(buffer->format) != format) ||
+        ((uint32_t(buffer->usage) & usage) != usage))
+    {
+        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+        sp<GraphicBuffer> graphicBuffer(
+                mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
+        if (graphicBuffer == 0) {
+            LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
+            return NO_MEMORY;
+        }
+        if (updateFormat) {
+            mPixelFormat = format;
+        }
         mSlots[buf].mGraphicBuffer = graphicBuffer;
+        mSlots[buf].mRequestBufferCalled = false;
         if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
             eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
             mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
             mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
         }
-        mAllocdBuffers.add(graphicBuffer);
+        returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
     }
-    return graphicBuffer;
+    return returnFlags;
 }
 
-status_t SurfaceTexture::dequeueBuffer(int *buf) {
-    LOGV("SurfaceTexture::dequeueBuffer");
+status_t SurfaceTexture::setSynchronousMode(bool enabled) {
     Mutex::Autolock lock(mMutex);
-    int found = INVALID_BUFFER_SLOT;
-    for (int i = 0; i < mBufferCount; i++) {
-        if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
-            mSlots[i].mOwnedByClient = true;
-            found = i;
-            break;
+
+    status_t err = OK;
+    if (!enabled) {
+        // going to asynchronous mode, drain the queue
+        while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
+            mDequeueCondition.wait(mMutex);
         }
     }
-    if (found == INVALID_BUFFER_SLOT) {
-        return -EBUSY;
+
+    if (mSynchronousMode != enabled) {
+        // - if we're going to asynchronous mode, the queue is guaranteed to be
+        // empty here
+        // - if the client set the number of buffers, we're guaranteed that
+        // we have at least 3 (because we don't allow less)
+        mSynchronousMode = enabled;
+        mDequeueCondition.signal();
     }
-    *buf = found;
-    return OK;
+    return err;
 }
 
-status_t SurfaceTexture::queueBuffer(int buf) {
+status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
     LOGV("SurfaceTexture::queueBuffer");
+
+    sp<FrameAvailableListener> listener;
+
+    { // scope for the lock
     Mutex::Autolock lock(mMutex);
-    if (buf < 0 || mBufferCount <= buf) {
+    if (buf < 0 || buf >= mBufferCount) {
         LOGE("queueBuffer: slot index out of range [0, %d]: %d",
                 mBufferCount, buf);
         return -EINVAL;
-    } else if (!mSlots[buf].mOwnedByClient) {
-        LOGE("queueBuffer: slot %d is not owned by the client", buf);
+    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+        LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
+                buf, mSlots[buf].mBufferState);
         return -EINVAL;
-    } else if (mSlots[buf].mGraphicBuffer == 0) {
+    } else if (buf == mCurrentTexture) {
+        LOGE("queueBuffer: slot %d is current!", buf);
+        return -EINVAL;
+    } else if (!mSlots[buf].mRequestBufferCalled) {
         LOGE("queueBuffer: slot %d was enqueued without requesting a buffer",
                 buf);
         return -EINVAL;
     }
-    mSlots[buf].mOwnedByClient = false;
-    mLastQueued = buf;
-    mLastQueuedCrop = mNextCrop;
-    mLastQueuedTransform = mNextTransform;
-    if (mFrameAvailableListener != 0) {
-        mFrameAvailableListener->onFrameAvailable();
+
+    if (mQueue.empty()) {
+        listener = mFrameAvailableListener;
+    }
+
+    if (mSynchronousMode) {
+        // in synchronous mode we queue all buffers in a FIFO
+        mQueue.push_back(buf);
+    } else {
+        // in asynchronous mode we only keep the most recent buffer
+        if (mQueue.empty()) {
+            mQueue.push_back(buf);
+        } else {
+            Fifo::iterator front(mQueue.begin());
+            // buffer currently queued is freed
+            mSlots[*front].mBufferState = BufferSlot::FREE;
+            // and we record the new buffer index in the queued list
+            *front = buf;
+        }
+    }
+
+    mSlots[buf].mBufferState = BufferSlot::QUEUED;
+    mSlots[buf].mLastQueuedCrop = mNextCrop;
+    mSlots[buf].mLastQueuedTransform = mNextTransform;
+    mSlots[buf].mLastQueuedTimestamp = timestamp;
+    mDequeueCondition.signal();
+    } // scope for the lock
+
+    // call back without lock held
+    if (listener != 0) {
+        listener->onFrameAvailable();
     }
     return OK;
 }
@@ -181,15 +445,17 @@
 void SurfaceTexture::cancelBuffer(int buf) {
     LOGV("SurfaceTexture::cancelBuffer");
     Mutex::Autolock lock(mMutex);
-    if (buf < 0 || mBufferCount <= buf) {
-        LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
-                buf);
+    if (buf < 0 || buf >= mBufferCount) {
+        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
         return;
-    } else if (!mSlots[buf].mOwnedByClient) {
-        LOGE("cancelBuffer: slot %d is not owned by the client", buf);
+    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+        LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
+                buf, mSlots[buf].mBufferState);
         return;
     }
-    mSlots[buf].mOwnedByClient = false;
+    mSlots[buf].mBufferState = BufferSlot::FREE;
+    mDequeueCondition.signal();
 }
 
 status_t SurfaceTexture::setCrop(const Rect& crop) {
@@ -208,50 +474,125 @@
 
 status_t SurfaceTexture::updateTexImage() {
     LOGV("SurfaceTexture::updateTexImage");
+
     Mutex::Autolock lock(mMutex);
 
-    // We always bind the texture even if we don't update its contents.
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
+    int buf = mCurrentTexture;
+    if (!mQueue.empty()) {
+        // in asynchronous mode the list is guaranteed to be one buffer deep,
+        // while in synchronous mode we use the oldest buffer
+        Fifo::iterator front(mQueue.begin());
+        buf = *front;
+        mQueue.erase(front);
+        if (mQueue.isEmpty()) {
+            mDequeueCondition.signal();
+        }
+    }
 
-    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
+    // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT,
     // so this check will fail until a buffer gets queued.
-    if (mCurrentTexture != mLastQueued) {
+    if (mCurrentTexture != buf) {
         // Update the GL texture object.
-        EGLImageKHR image = mSlots[mLastQueued].mEglImage;
+        EGLImageKHR image = mSlots[buf].mEglImage;
         if (image == EGL_NO_IMAGE_KHR) {
             EGLDisplay dpy = eglGetCurrentDisplay();
-            sp<GraphicBuffer> graphicBuffer = mSlots[mLastQueued].mGraphicBuffer;
-            image = createImage(dpy, graphicBuffer);
-            mSlots[mLastQueued].mEglImage = image;
-            mSlots[mLastQueued].mEglDisplay = dpy;
+            image = createImage(dpy, mSlots[buf].mGraphicBuffer);
+            mSlots[buf].mEglImage = image;
+            mSlots[buf].mEglDisplay = dpy;
+            if (image == EGL_NO_IMAGE_KHR) {
+                // NOTE: if dpy was invalid, createImage() is guaranteed to
+                // fail. so we'd end up here.
+                return -EINVAL;
+            }
         }
 
         GLint error;
         while ((error = glGetError()) != GL_NO_ERROR) {
-            LOGE("GL error cleared before updating SurfaceTexture: %#04x", error);
+            LOGW("updateTexImage: clearing GL error: %#04x", error);
         }
-        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
+
+        GLenum target = getTextureTarget(mSlots[buf].mGraphicBuffer->format);
+        if (target != mCurrentTextureTarget) {
+            glDeleteTextures(1, &mTexName);
+        }
+        glBindTexture(target, mTexName);
+        glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image);
+
         bool failed = false;
         while ((error = glGetError()) != GL_NO_ERROR) {
             LOGE("error binding external texture image %p (slot %d): %#04x",
-                    image, mLastQueued, error);
+                    image, buf, error);
             failed = true;
         }
         if (failed) {
             return -EINVAL;
         }
 
+        if (mCurrentTexture != INVALID_BUFFER_SLOT) {
+            // the current buffer becomes FREE if it was still in the queued
+            // state. If it has already been given to the client
+            // (synchronous mode), then it stays in DEQUEUED state.
+            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
+                mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
+        }
+
         // Update the SurfaceTexture state.
-        mCurrentTexture = mLastQueued;
-        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
-        mCurrentCrop = mLastQueuedCrop;
-        mCurrentTransform = mLastQueuedTransform;
+        mCurrentTexture = buf;
+        mCurrentTextureTarget = target;
+        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
+        mCurrentCrop = mSlots[buf].mLastQueuedCrop;
+        mCurrentTransform = mSlots[buf].mLastQueuedTransform;
+        mCurrentTimestamp = mSlots[buf].mLastQueuedTimestamp;
+        mDequeueCondition.signal();
+    } else {
+        // We always bind the texture even if we don't update its contents.
+        glBindTexture(mCurrentTextureTarget, mTexName);
     }
     return OK;
 }
 
+size_t SurfaceTexture::getQueuedCount() const {
+    Mutex::Autolock lock(mMutex);
+    return mQueue.size();
+}
+
+bool SurfaceTexture::isExternalFormat(uint32_t format)
+{
+    switch (format) {
+    // supported YUV formats
+    case HAL_PIXEL_FORMAT_YV12:
+    // Legacy/deprecated YUV formats
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        return true;
+    }
+
+    // Any OEM format needs to be considered
+    if (format>=0x100 && format<=0x1FF)
+        return true;
+
+    return false;
+}
+
+GLenum SurfaceTexture::getTextureTarget(uint32_t format)
+{
+    GLenum target = GL_TEXTURE_2D;
+#if defined(GL_OES_EGL_image_external)
+    if (isExternalFormat(format)) {
+        target = GL_TEXTURE_EXTERNAL_OES;
+    }
+#endif
+    return target;
+}
+
+GLenum SurfaceTexture::getCurrentTextureTarget() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTextureTarget;
+}
+
 void SurfaceTexture::getTransformMatrix(float mtx[16]) {
-    LOGV("SurfaceTexture::updateTexImage");
+    LOGV("SurfaceTexture::getTransformMatrix");
     Mutex::Autolock lock(mMutex);
 
     float xform[16];
@@ -304,10 +645,10 @@
         } else {
             tx = 0.0f;
         }
-        if (mCurrentCrop.right < buf->getWidth()) {
+        if (mCurrentCrop.right < int32_t(buf->getWidth())) {
             xshrink++;
         }
-        if (mCurrentCrop.bottom < buf->getHeight()) {
+        if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
             ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
                     float(buf->getHeight());
             yshrink++;
@@ -342,6 +683,12 @@
     mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
 }
 
+nsecs_t SurfaceTexture::getTimestamp() {
+    LOGV("SurfaceTexture::getTimestamp");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTimestamp;
+}
+
 void SurfaceTexture::setFrameAvailableListener(
         const sp<FrameAvailableListener>& l) {
     LOGV("SurfaceTexture::setFrameAvailableListener");
@@ -357,26 +704,13 @@
 void SurfaceTexture::freeAllBuffers() {
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i].mGraphicBuffer = 0;
-        mSlots[i].mOwnedByClient = false;
+        mSlots[i].mBufferState = BufferSlot::FREE;
         if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
             eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
             mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
             mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
         }
     }
-
-    int exceptBuf = -1;
-    for (size_t i = 0; i < mAllocdBuffers.size(); i++) {
-        if (mAllocdBuffers[i] == mCurrentTextureBuf) {
-            exceptBuf = i;
-            break;
-        }
-    }
-    mAllocdBuffers.clear();
-    if (exceptBuf >= 0) {
-        mAllocdBuffers.add(mCurrentTextureBuf);
-    }
-    mGraphicBufferAlloc->freeAllGraphicBuffersExcept(exceptBuf);
 }
 
 EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
@@ -388,16 +722,121 @@
     };
     EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
-    EGLint error = eglGetError();
-    if (error != EGL_SUCCESS) {
+    if (image == EGL_NO_IMAGE_KHR) {
+        EGLint error = eglGetError();
         LOGE("error creating EGLImage: %#x", error);
-    } else if (image == EGL_NO_IMAGE_KHR) {
-        LOGE("no error reported, but no image was returned by "
-                "eglCreateImageKHR");
     }
     return image;
 }
 
+sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTextureBuf;
+}
+
+Rect SurfaceTexture::getCurrentCrop() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentCrop;
+}
+
+uint32_t SurfaceTexture::getCurrentTransform() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTransform;
+}
+
+int SurfaceTexture::query(int what, int* outValue)
+{
+    Mutex::Autolock lock(mMutex);
+    int value;
+    switch (what) {
+    case NATIVE_WINDOW_WIDTH:
+        value = mDefaultWidth;
+        if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
+            value = mCurrentTextureBuf->width;
+        break;
+    case NATIVE_WINDOW_HEIGHT:
+        value = mDefaultHeight;
+        if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
+            value = mCurrentTextureBuf->height;
+        break;
+    case NATIVE_WINDOW_FORMAT:
+        value = mPixelFormat;
+        break;
+    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+        value = mSynchronousMode ?
+                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
+        break;
+    default:
+        return BAD_VALUE;
+    }
+    outValue[0] = value;
+    return NO_ERROR;
+}
+
+void SurfaceTexture::dump(String8& result) const
+{
+    char buffer[1024];
+    dump(result, "", buffer, 1024);
+}
+
+void SurfaceTexture::dump(String8& result, const char* prefix,
+        char* buffer, size_t SIZE) const
+{
+    Mutex::Autolock _l(mMutex);
+    snprintf(buffer, SIZE,
+            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
+            "mPixelFormat=%d, mTexName=%d\n",
+            prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
+            mPixelFormat, mTexName);
+    result.append(buffer);
+
+    String8 fifo;
+    int fifoSize = 0;
+    Fifo::const_iterator i(mQueue.begin());
+    while (i != mQueue.end()) {
+        snprintf(buffer, SIZE, "%02d ", *i++);
+        fifoSize++;
+        fifo.append(buffer);
+    }
+
+    snprintf(buffer, SIZE,
+            "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d, target=0x%04x}\n"
+            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
+            ,
+            prefix, mCurrentCrop.left,
+            mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
+            mCurrentTransform, mCurrentTexture, mCurrentTextureTarget,
+            prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
+            mCurrentTransform, fifoSize, fifo.string()
+    );
+    result.append(buffer);
+
+    struct {
+        const char * operator()(int state) const {
+            switch (state) {
+                case BufferSlot::DEQUEUED: return "DEQUEUED";
+                case BufferSlot::QUEUED: return "QUEUED";
+                case BufferSlot::FREE: return "FREE";
+                default: return "Unknown";
+            }
+        }
+    } stateName;
+
+    for (int i=0 ; i<mBufferCount ; i++) {
+        const BufferSlot& slot(mSlots[i]);
+        snprintf(buffer, SIZE,
+                "%s%s[%02d] state=%-8s, crop=[%d,%d,%d,%d], transform=0x%02x, "
+                "timestamp=%lld\n"
+                ,
+                prefix, (i==mCurrentTexture)?">":" ", i, stateName(slot.mBufferState),
+                slot.mLastQueuedCrop.left, slot.mLastQueuedCrop.top,
+                slot.mLastQueuedCrop.right, slot.mLastQueuedCrop.bottom,
+                slot.mLastQueuedTransform, slot.mLastQueuedTimestamp
+        );
+        result.append(buffer);
+    }
+}
+
 static void mtxMul(float out[16], const float a[16], const float b[16]) {
     out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
     out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 7f1d9cb..6f10320 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -25,8 +25,11 @@
 
 SurfaceTextureClient::SurfaceTextureClient(
         const sp<ISurfaceTexture>& surfaceTexture):
-        mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
-        mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
+        mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0),
+        mReqHeight(0), mReqFormat(0), mReqUsage(0),
+        mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0),
+        mQueryWidth(0), mQueryHeight(0), mQueryFormat(0),
+        mMutex() {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = setSwapInterval;
     ANativeWindow::dequeueBuffer    = dequeueBuffer;
@@ -36,6 +39,9 @@
     ANativeWindow::query            = query;
     ANativeWindow::perform          = perform;
 
+    const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
+    const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
+
     // Get a reference to the allocator.
     mAllocator = mSurfaceTexture->getAllocator();
 }
@@ -50,31 +56,32 @@
 }
 
 int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window,
-        android_native_buffer_t** buffer) {
+        ANativeWindowBuffer** buffer) {
     SurfaceTextureClient* c = getSelf(window);
     return c->dequeueBuffer(buffer);
 }
 
 int SurfaceTextureClient::cancelBuffer(ANativeWindow* window,
-        android_native_buffer_t* buffer) {
+        ANativeWindowBuffer* buffer) {
     SurfaceTextureClient* c = getSelf(window);
     return c->cancelBuffer(buffer);
 }
 
 int SurfaceTextureClient::lockBuffer(ANativeWindow* window,
-        android_native_buffer_t* buffer) {
+        ANativeWindowBuffer* buffer) {
     SurfaceTextureClient* c = getSelf(window);
     return c->lockBuffer(buffer);
 }
 
 int SurfaceTextureClient::queueBuffer(ANativeWindow* window,
-        android_native_buffer_t* buffer) {
+        ANativeWindowBuffer* buffer) {
     SurfaceTextureClient* c = getSelf(window);
     return c->queueBuffer(buffer);
 }
 
-int SurfaceTextureClient::query(ANativeWindow* window, int what, int* value) {
-    SurfaceTextureClient* c = getSelf(window);
+int SurfaceTextureClient::query(const ANativeWindow* window,
+                                int what, int* value) {
+    const SurfaceTextureClient* c = getSelf(window);
     return c->query(what, value);
 }
 
@@ -86,29 +93,47 @@
 }
 
 int SurfaceTextureClient::setSwapInterval(int interval) {
-    return INVALID_OPERATION;
+    // EGL specification states:
+    //  interval is silently clamped to minimum and maximum implementation
+    //  dependent values before being stored.
+    // Although we don't have to, we apply the same logic here.
+
+    if (interval < minSwapInterval)
+        interval = minSwapInterval;
+
+    if (interval > maxSwapInterval)
+        interval = maxSwapInterval;
+
+    status_t res = mSurfaceTexture->setSynchronousMode(interval ? true : false);
+
+    return res;
 }
 
 int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
     LOGV("SurfaceTextureClient::dequeueBuffer");
     Mutex::Autolock lock(mMutex);
     int buf = -1;
-    status_t err = mSurfaceTexture->dequeueBuffer(&buf);
-    if (err < 0) {
-        LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
-        return err;
+    status_t result = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,
+            mReqFormat, mReqUsage);
+    if (result < 0) {
+        LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
+             "failed: %d", result, mReqWidth, mReqHeight, mReqFormat, mReqUsage);
+        return result;
     }
     sp<GraphicBuffer>& gbuf(mSlots[buf]);
-    if (gbuf == 0 || gbuf->getWidth() != mReqWidth ||
-        gbuf->getHeight() != mReqHeight ||
-        uint32_t(gbuf->getPixelFormat()) != mReqFormat ||
-        (gbuf->getUsage() & mReqUsage) != mReqUsage) {
-        gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight,
-                mReqFormat, mReqUsage);
+    if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
+        freeAllBuffers();
+    }
+
+    if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
+        gbuf = mSurfaceTexture->requestBuffer(buf);
         if (gbuf == 0) {
             LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
             return NO_MEMORY;
         }
+        mQueryWidth  = gbuf->width;
+        mQueryHeight = gbuf->height;
+        mQueryFormat = gbuf->format;
     }
     *buffer = gbuf.get();
     return OK;
@@ -135,40 +160,36 @@
 int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
     LOGV("SurfaceTextureClient::queueBuffer");
     Mutex::Autolock lock(mMutex);
+    int64_t timestamp;
+    if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
+        timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+        LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms",
+             timestamp / 1000000.f);
+    } else {
+        timestamp = mTimestamp;
+    }
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         if (mSlots[i]->handle == buffer->handle) {
-            return mSurfaceTexture->queueBuffer(i);
+            return mSurfaceTexture->queueBuffer(i, timestamp);
         }
     }
     LOGE("queueBuffer: unknown buffer queued");
     return BAD_VALUE;
 }
 
-int SurfaceTextureClient::query(int what, int* value) {
+int SurfaceTextureClient::query(int what, int* value) const {
     LOGV("SurfaceTextureClient::query");
-    Mutex::Autolock lock(mMutex);
     switch (what) {
-    case NATIVE_WINDOW_WIDTH:
-    case NATIVE_WINDOW_HEIGHT:
-        // XXX: How should SurfaceTexture behave if setBuffersGeometry didn't
-        // override the size?
-        *value = 0;
-        return NO_ERROR;
-    case NATIVE_WINDOW_FORMAT:
-        *value = DEFAULT_FORMAT;
-        return NO_ERROR;
-    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
-        *value = MIN_UNDEQUEUED_BUFFERS;
-        return NO_ERROR;
     case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
-        // SurfaceTextureClient currently never queues frames to SurfaceFlinger.
+        // TODO: this is not needed anymore
         *value = 0;
         return NO_ERROR;
     case NATIVE_WINDOW_CONCRETE_TYPE:
+        // TODO: this is not needed anymore
         *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
         return NO_ERROR;
     }
-    return BAD_VALUE;
+    return mSurfaceTexture->query(what, value);
 }
 
 int SurfaceTextureClient::perform(int operation, va_list args)
@@ -196,6 +217,9 @@
     case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
         res = dispatchSetBuffersTransform(args);
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+        res = dispatchSetBuffersTimestamp(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -240,18 +264,56 @@
     return setBuffersTransform(transform);
 }
 
+int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
+    int64_t timestamp = va_arg(args, int64_t);
+    return setBuffersTimestamp(timestamp);
+}
+
 int SurfaceTextureClient::connect(int api) {
     LOGV("SurfaceTextureClient::connect");
-    // XXX: Implement this!
-    return INVALID_OPERATION;
+    Mutex::Autolock lock(mMutex);
+    int err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+            if (mConnectedApi) {
+                err = -EINVAL;
+            } else {
+                mConnectedApi = api;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
 }
 
 int SurfaceTextureClient::disconnect(int api) {
     LOGV("SurfaceTextureClient::disconnect");
-    // XXX: Implement this!
-    return INVALID_OPERATION;
+    Mutex::Autolock lock(mMutex);
+    int err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+            if (mConnectedApi == api) {
+                mConnectedApi = 0;
+            } else {
+                err = -EINVAL;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
 }
 
+int SurfaceTextureClient::getConnectedApi() const
+{
+    Mutex::Autolock lock(mMutex);
+    return mConnectedApi;
+}
+
+
 int SurfaceTextureClient::setUsage(uint32_t reqUsage)
 {
     LOGV("SurfaceTextureClient::setUsage");
@@ -323,6 +385,14 @@
     return err;
 }
 
+int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
+{
+    LOGV("SurfaceTextureClient::setBuffersTimestamp");
+    Mutex::Autolock lock(mMutex);
+    mTimestamp = timestamp;
+    return NO_ERROR;
+}
+
 void SurfaceTextureClient::freeAllBuffers() {
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i] = 0;
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index 7516299..8d3a9b5 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -9,6 +9,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := \
+    Surface_test.cpp \
     SurfaceTextureClient_test.cpp \
     SurfaceTexture_test.cpp \
 
@@ -20,7 +21,6 @@
 	libcutils \
 	libgui \
 	libstlport \
-	libsurfaceflinger_client \
 	libui \
 	libutils \
 
@@ -36,9 +36,6 @@
 
 include $(BUILD_EXECUTABLE)
 
-# Build the manual test programs.
-include $(call all-subdir-makefiles)
-
 endif
 
 # Include subdirectory makefiles
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 94b05bc..59a4cc5 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -17,23 +17,78 @@
 #include <EGL/egl.h>
 #include <gtest/gtest.h>
 #include <gui/SurfaceTextureClient.h>
+#include <utils/threads.h>
 
 namespace android {
 
 class SurfaceTextureClientTest : public ::testing::Test {
 protected:
+    SurfaceTextureClientTest():
+            mEglDisplay(EGL_NO_DISPLAY),
+            mEglSurface(EGL_NO_SURFACE),
+            mEglContext(EGL_NO_CONTEXT) {
+    }
+
     virtual void SetUp() {
         mST = new SurfaceTexture(123);
         mSTC = new SurfaceTextureClient(mST);
+
+        // We need a valid GL context so we can test updateTexImage()
+        // This initializes EGL and create a dummy GL context with a
+        // pbuffer render target.
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+
+        EGLint majorVersion, minorVersion;
+        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        EGLConfig myConfig;
+        EGLint numConfigs = 0;
+        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(),
+                &myConfig, 1, &numConfigs));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        EGLint pbufferAttribs[] = {
+            EGL_WIDTH, 16,
+            EGL_HEIGHT, 16,
+            EGL_NONE };
+        mEglSurface = eglCreatePbufferSurface(mEglDisplay, myConfig, pbufferAttribs);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+
+        mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, 0);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
+
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
     }
 
     virtual void TearDown() {
         mST.clear();
         mSTC.clear();
+        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        eglDestroyContext(mEglDisplay, mEglContext);
+        eglDestroySurface(mEglDisplay, mEglSurface);
+        eglTerminate(mEglDisplay);
+    }
+
+    virtual EGLint const* getConfigAttribs() {
+        static EGLint sDefaultConfigAttribs[] = {
+            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+            EGL_NONE
+        };
+
+        return sDefaultConfigAttribs;
     }
 
     sp<SurfaceTexture> mST;
     sp<SurfaceTextureClient> mSTC;
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurface;
+    EGLContext mEglContext;
 };
 
 TEST_F(SurfaceTextureClientTest, GetISurfaceTextureIsNotNull) {
@@ -64,7 +119,7 @@
     ASSERT_EQ(BAD_VALUE, ANativeWindow_lock(anw.get(), &buf, NULL));
 }
 
-TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceFails) {
+TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) {
     sp<ANativeWindow> anw(mSTC);
 
     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -94,10 +149,358 @@
 
     EGLSurface eglSurface = eglCreateWindowSurface(dpy, myConfig, anw.get(),
             NULL);
-    ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
-    ASSERT_EQ(EGL_BAD_NATIVE_WINDOW, eglGetError());
+    EXPECT_NE(EGL_NO_SURFACE, eglSurface);
+    EXPECT_EQ(EGL_SUCCESS, eglGetError());
 
     eglTerminate(dpy);
 }
 
+TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) {
+    sp<ANativeWindow> anw(mSTC);
+
+    EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), -1,  0,  0));
+    EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(),  0, -1,  0));
+    EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(),  0,  0, -1));
+    EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), -1, -1,  0));
+    EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(),  0,  8,  0));
+    EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(),  8,  0,  0));
+}
+
+TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
+    sp<ANativeWindow> anw(mSTC);
+    ANativeWindowBuffer* buf;
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(1, buf->width);
+    EXPECT_EQ(1, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
+    sp<ANativeWindow> anw(mSTC);
+    ANativeWindowBuffer* buf;
+    EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, PIXEL_FORMAT_RGB_565));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(16, buf->width);
+    EXPECT_EQ(8, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
+    sp<ANativeWindow> anw(mSTC);
+    ANativeWindowBuffer* buf;
+    EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(1, buf->width);
+    EXPECT_EQ(1, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
+    sp<ANativeWindow> anw(mSTC);
+    ANativeWindowBuffer* buf;
+    EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(16, buf->width);
+    EXPECT_EQ(8, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
+    sp<ANativeWindow> anw(mSTC);
+    ANativeWindowBuffer* buf;
+    EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(16, buf->width);
+    EXPECT_EQ(8, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+    EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, 0));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(1, buf->width);
+    EXPECT_EQ(1, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
+    sp<ANativeWindow> anw(mSTC);
+    ANativeWindowBuffer* buf;
+    EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(1, buf->width);
+    EXPECT_EQ(1, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+    EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(16, buf->width);
+    EXPECT_EQ(8, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    ANativeWindowBuffer* buf;
+    EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+    EXPECT_EQ(16, buf->width);
+    EXPECT_EQ(8, buf->height);
+    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    ANativeWindowBuffer* buf[2];
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    EXPECT_NE(buf[0], buf[1]);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+    EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    EXPECT_NE(buf[0], buf[1]);
+    EXPECT_EQ(16, buf[0]->width);
+    EXPECT_EQ(16, buf[1]->width);
+    EXPECT_EQ(8, buf[0]->height);
+    EXPECT_EQ(8, buf[1]->height);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    ANativeWindowBuffer* buf[2];
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+    EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    EXPECT_NE(buf[0], buf[1]);
+    EXPECT_EQ(16, buf[0]->width);
+    EXPECT_EQ(16, buf[1]->width);
+    EXPECT_EQ(8, buf[0]->height);
+    EXPECT_EQ(8, buf[1]->height);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+    EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 12, 24, 0));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    EXPECT_NE(buf[0], buf[1]);
+    EXPECT_EQ(12, buf[0]->width);
+    EXPECT_EQ(12, buf[1]->width);
+    EXPECT_EQ(24, buf[0]->height);
+    EXPECT_EQ(24, buf[1]->height);
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, st->setSynchronousMode(false));
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(OK, st->updateTexImage());
+
+    ASSERT_EQ(OK, st->setSynchronousMode(true));
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(OK, st->updateTexImage());
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, st->setSynchronousMode(true));
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+    EXPECT_NE(buf[0], buf[1]);
+    EXPECT_NE(buf[1], buf[2]);
+    EXPECT_NE(buf[2], buf[0]);
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, st->setSynchronousMode(true));
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+    EXPECT_NE(buf[0], buf[1]);
+    EXPECT_NE(buf[1], buf[2]);
+    EXPECT_NE(buf[2], buf[0]);
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, st->setSynchronousMode(true));
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
+
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    EXPECT_NE(buf[0], buf[1]);
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+    EXPECT_NE(buf[1], buf[2]);
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDequeueCurrent) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    android_native_buffer_t* firstBuf;
+    ASSERT_EQ(OK, st->setSynchronousMode(true));
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &firstBuf));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), firstBuf));
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), firstBuf);
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+    EXPECT_NE(buf[0], buf[1]);
+    EXPECT_NE(buf[1], buf[2]);
+    EXPECT_NE(buf[2], buf[0]);
+    EXPECT_EQ(firstBuf, buf[2]);
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, st->setSynchronousMode(true));
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+    EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    EXPECT_EQ(-EBUSY, anw->dequeueBuffer(anw.get(), &buf[2]));
+
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+
+    EXPECT_EQ(OK, st->updateTexImage());
+    EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+
+    EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[2]));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeWaitRetire) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+
+    class MyThread : public Thread {
+        sp<SurfaceTexture> st;
+        EGLContext ctx;
+        EGLSurface sur;
+        EGLDisplay dpy;
+        bool mBufferRetired;
+        Mutex mLock;
+        virtual bool threadLoop() {
+            eglMakeCurrent(dpy, sur, sur, ctx);
+            usleep(20000);
+            Mutex::Autolock _l(mLock);
+            st->updateTexImage();
+            mBufferRetired = true;
+            eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+            return false;
+        }
+    public:
+        MyThread(const sp<SurfaceTexture>& st)
+            : st(st), mBufferRetired(false) {
+            ctx = eglGetCurrentContext();
+            sur = eglGetCurrentSurface(EGL_DRAW);
+            dpy = eglGetCurrentDisplay();
+            eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        }
+        ~MyThread() {
+            eglMakeCurrent(dpy, sur, sur, ctx);
+        }
+        void bufferDequeued() {
+            Mutex::Autolock _l(mLock);
+            EXPECT_EQ(true, mBufferRetired);
+        }
+    };
+
+    android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, st->setSynchronousMode(true));
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+    // dequeue/queue/update so we have a current buffer
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    st->updateTexImage();
+
+    MyThread* thread = new MyThread(st);
+    sp<Thread> threadBase(thread);
+
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+    thread->run();
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+    thread->bufferDequeued();
+    thread->requestExitAndWait();
+}
+
 }
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 4184463..8747ba5 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -76,7 +76,7 @@
             mComposerClient = new SurfaceComposerClient;
             ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
 
-            mSurfaceControl = mComposerClient->createSurface(getpid(),
+            mSurfaceControl = mComposerClient->createSurface(
                     String8("Test Surface"), 0,
                     getSurfaceWidth(), getSurfaceHeight(),
                     PIXEL_FORMAT_RGB_888, 0);
@@ -476,7 +476,7 @@
     ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
             GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
 
-    android_native_buffer_t* anb;
+    ANativeWindowBuffer* anb;
     ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
     ASSERT_TRUE(anb != NULL);
 
@@ -524,7 +524,7 @@
     ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
             GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
 
-    android_native_buffer_t* anb;
+    ANativeWindowBuffer* anb;
     ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
     ASSERT_TRUE(anb != NULL);
 
@@ -583,7 +583,7 @@
 
         ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
 
-        android_native_buffer_t* anb;
+        ANativeWindowBuffer* anb;
         ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
         ASSERT_TRUE(anb != NULL);
 
diff --git a/libs/surfaceflinger_client/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
similarity index 97%
rename from libs/surfaceflinger_client/tests/Surface_test.cpp
rename to libs/gui/tests/Surface_test.cpp
index fd07479..35c8640 100644
--- a/libs/surfaceflinger_client/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -30,7 +30,7 @@
         mComposerClient = new SurfaceComposerClient;
         ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
 
-        mSurfaceControl = mComposerClient->createSurface(getpid(),
+        mSurfaceControl = mComposerClient->createSurface(
                 String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGB_888, 0);
 
         ASSERT_TRUE(mSurfaceControl != NULL);
@@ -93,7 +93,7 @@
     ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(),
             GRALLOC_USAGE_PROTECTED));
     ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3));
-    android_native_buffer_t* buf = 0;
+    ANativeWindowBuffer* buf = 0;
     for (int i = 0; i < 4; i++) {
         // Loop to make sure SurfaceFlinger has retired a protected buffer.
         ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk
index 4a0faf0..267e3ed 100644
--- a/libs/surfaceflinger_client/Android.mk
+++ b/libs/surfaceflinger_client/Android.mk
@@ -1,22 +1,9 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= \
-	ISurfaceComposer.cpp \
-	ISurface.cpp \
-	ISurfaceComposerClient.cpp \
-	IGraphicBufferAlloc.cpp \
-	LayerState.cpp \
-	SharedBufferStack.cpp \
-	Surface.cpp \
-	SurfaceComposerClient.cpp
+LOCAL_SRC_FILES:=
 
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-	libbinder \
-	libhardware \
-	libui
+LOCAL_SHARED_LIBRARIES := 
 
 LOCAL_MODULE:= libsurfaceflinger_client
 
diff --git a/libs/surfaceflinger_client/tests/Android.mk b/libs/surfaceflinger_client/tests/Android.mk
deleted file mode 100644
index 212b8e7..0000000
--- a/libs/surfaceflinger_client/tests/Android.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-ifneq ($(TARGET_SIMULATOR),true)
-
-# Build the unit tests.
-test_src_files := \
-    Surface_test.cpp \
-
-shared_libraries := \
-	libcutils \
-	libutils \
-	libbinder \
-	libsurfaceflinger_client \
-	libstlport \
-
-static_libraries := \
-	libgtest \
-	libgtest_main \
-
-c_includes := \
-    bionic \
-    bionic/libstdc++/include \
-    external/gtest/include \
-    external/stlport/stlport \
-
-module_tags := tests
-
-$(foreach file,$(test_src_files), \
-    $(eval include $(CLEAR_VARS)) \
-    $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
-    $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
-    $(eval LOCAL_C_INCLUDES := $(c_includes)) \
-    $(eval LOCAL_SRC_FILES := $(file)) \
-    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
-    $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
-    $(eval include $(BUILD_EXECUTABLE)) \
-)
-
-# Build the manual test programs.
-include $(call all-subdir-makefiles)
-
-endif
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk b/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk
deleted file mode 100644
index d3dfe04..0000000
--- a/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	SharedBufferStackTest.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-    libui \
-    libsurfaceflinger_client
-
-LOCAL_MODULE:= test-sharedbufferstack
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_EXECUTABLE)
diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
deleted file mode 100644
index 7ef5926..0000000
--- a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#undef NDEBUG
-
-#include <assert.h>
-#include <cutils/memory.h>
-#include <cutils/log.h>
-#include <utils/Errors.h>
-#include <private/surfaceflinger/SharedBufferStack.h>
-
-using namespace android;
-
-void log(const char* prefix, int *b, size_t num);
-void test0(SharedBufferServer& s, SharedBufferClient& c, size_t num, int* list);
-
-// ----------------------------------------------------------------------------
-
-int main(int argc, char** argv)
-{
-    SharedClient client;
-    sp<SharedBufferServer> ps(new SharedBufferServer(&client, 0, 4, 0));
-    SharedBufferServer& s(*ps);
-    SharedBufferClient c(&client, 0, 4, 0);
-
-    printf("basic test 0\n");
-    int list0[4] = {0, 1, 2, 3};
-    test0(s, c, 4, list0);
-
-    printf("basic test 1\n");
-    int list1[4] = {2, 1, 0, 3};
-    test0(s, c, 4, list1);
-
-    int b = c.dequeue();
-    c.lock(b);
-    c.queue(b);
-    s.retireAndLock();
-
-    printf("basic test 2\n");
-    int list2[4] = {1, 2, 3, 0};
-    test0(s, c, 4, list2);
-
-
-    printf("resize test\n");
-    class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback {
-        SharedBufferServer& s;
-        virtual status_t operator()(int bufferCount) const {
-            return s.resize(bufferCount);
-        }
-    public:
-        SetBufferCountIPC(SharedBufferServer& s) : s(s) { }
-    } resize(s);
-
-    c.setBufferCount(6, resize);
-    int list3[6] = {3, 2, 1, 4, 5, 0};
-    test0(s, c, 6, list3);
-
-    c.setBufferCount(4, resize);
-    int list4[4] = {1, 2, 3, 0};
-    test0(s, c, 4, list4);
-
-    return 0;
-}
-
-void log(const char* prefix, int *b, size_t num)
-{
-    printf("%s: ", prefix);
-    for (size_t i=0 ; i<num ; i++) {
-        printf("%d ", b[i]);
-    }
-    printf("\n");
-}
-
-// ----------------------------------------------------------------------------
-
-void test0(
-        SharedBufferServer& s,
-        SharedBufferClient& c,
-        size_t num,
-        int* list)
-{
-    status_t err;
-    int b[num], u[num], r[num];
-
-    for (size_t i=0 ; i<num ; i++) {
-        b[i] = c.dequeue();
-        assert(b[i]==list[i]);
-    }
-    log("DQ", b, num);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        err = c.lock(b[i]);
-        assert(err==0);
-    }
-    log("LK", b, num-1);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        err = c.queue(b[i]);
-        assert(err==0);
-    }
-    log(" Q", b, num-1);
-
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        r[i] = s.retireAndLock();
-        assert(r[i]==list[i]);
-        err = s.unlock(r[i]);
-        assert(err == 0);
-    }
-    log("RT", r, num-1);
-
-    err = c.lock(b[num-1]);
-    assert(err == 0);
-    log("LK", b+num-1, 1);
-
-    err = c.queue(b[num-1]);
-    assert(err == 0);
-    log(" Q", b+num-1, 1);
-
-    r[num-1] = s.retireAndLock();
-    assert(r[num-1]==list[num-1]);
-    err = s.unlock(r[num-1]);
-    assert(err == 0);
-    log("RT", r+num-1, 1);
-
-    // ------------------------------------
-    printf("\n");
-
-    for (size_t i=0 ; i<num ; i++) {
-        b[i] = c.dequeue();
-        assert(b[i]==list[i]);
-    }
-    log("DQ", b, num);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        err = c.lock(b[i]);
-        assert(err==0);
-    }
-    log("LK", b, num-1);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        u[i] = b[num-2-i];
-    }
-    u[num-1] = b[num-1];
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        err = c.queue(u[i]);
-        assert(err==0);
-    }
-    log(" Q", u, num-1);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        r[i] = s.retireAndLock();
-        assert(r[i]==u[i]);
-        err = s.unlock(r[i]);
-        assert(err == 0);
-    }
-    log("RT", r, num-1);
-
-    err = c.lock(b[num-1]);
-    assert(err == 0);
-    log("LK", b+num-1, 1);
-
-    err = c.queue(b[num-1]);
-    assert(err == 0);
-    log(" Q", b+num-1, 1);
-
-    r[num-1] = s.retireAndLock();
-    assert(r[num-1]==list[num-1]);
-    err = s.unlock(r[num-1]);
-    assert(err == 0);
-    log("RT", r+num-1, 1);
-
-    // ------------------------------------
-    printf("\n");
-
-    for (size_t i=0 ; i<num ; i++) {
-        b[i] = c.dequeue();
-        assert(b[i]==u[i]);
-    }
-    log("DQ", b, num);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        err = c.lock(b[i]);
-        assert(err==0);
-    }
-    log("LK", b, num-1);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        err = c.queue(b[i]);
-        assert(err==0);
-    }
-    log(" Q", b, num-1);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        r[i] = s.retireAndLock();
-        assert(r[i]==u[i]);
-        err = s.unlock(r[i]);
-        assert(err == 0);
-    }
-    log("RT", r, num-1);
-
-    err = c.lock(u[num-1]);
-    assert(err == 0);
-    log("LK", u+num-1, 1);
-
-    err = c.queue(u[num-1]);
-    assert(err == 0);
-    log(" Q", u+num-1, 1);
-
-    r[num-1] = s.retireAndLock();
-    assert(r[num-1]==u[num-1]);
-    err = s.unlock(r[num-1]);
-    assert(err == 0);
-    log("RT", r+num-1, 1);
-
-    // ------------------------------------
-    printf("\n");
-
-    b[0] = c.dequeue();
-    assert(b[0]==u[0]);
-    log("DQ", b, 1);
-
-    c.undoDequeue(b[0]);
-    assert(err == 0);
-    log("UDQ", b, 1);
-
-    // ------------------------------------
-    printf("\n");
-
-    for (size_t i=0 ; i<num ; i++) {
-        b[i] = c.dequeue();
-        assert(b[i]==u[i]);
-    }
-    log("DQ", b, num);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        err = c.lock(b[i]);
-        assert(err==0);
-    }
-    log("LK", b, num-1);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        err = c.queue(b[i]);
-        assert(err==0);
-    }
-    log(" Q", b, num-1);
-
-    for (size_t i=0 ; i<num-1 ; i++) {
-        r[i] = s.retireAndLock();
-        assert(r[i]==u[i]);
-        err = s.unlock(r[i]);
-        assert(err == 0);
-    }
-    log("RT", r, num-1);
-
-    err = c.lock(u[num-1]);
-    assert(err == 0);
-    log("LK", u+num-1, 1);
-
-    err = c.queue(u[num-1]);
-    assert(err == 0);
-    log(" Q", u+num-1, 1);
-
-    r[num-1] = s.retireAndLock();
-    assert(r[num-1]==u[num-1]);
-    err = s.unlock(r[num-1]);
-    assert(err == 0);
-    log("RT", r+num-1, 1);
-    printf("\n");
-}
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index dc223f9..4393504 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -47,16 +47,16 @@
 
 class NativeBuffer 
     : public EGLNativeBase<
-        android_native_buffer_t, 
+        ANativeWindowBuffer, 
         NativeBuffer, 
         LightRefBase<NativeBuffer> >
 {
 public:
     NativeBuffer(int w, int h, int f, int u) : BASE() {
-        android_native_buffer_t::width  = w;
-        android_native_buffer_t::height = h;
-        android_native_buffer_t::format = f;
-        android_native_buffer_t::usage  = u;
+        ANativeWindowBuffer::width  = w;
+        ANativeWindowBuffer::height = h;
+        ANativeWindowBuffer::format = f;
+        ANativeWindowBuffer::usage  = u;
     }
 private:
     friend class LightRefBase<NativeBuffer>;    
@@ -201,7 +201,7 @@
 }
 
 int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, 
-        android_native_buffer_t** buffer)
+        ANativeWindowBuffer** buffer)
 {
     FramebufferNativeWindow* self = getSelf(window);
     Mutex::Autolock _l(self->mutex);
@@ -229,7 +229,7 @@
 }
 
 int FramebufferNativeWindow::lockBuffer(ANativeWindow* window, 
-        android_native_buffer_t* buffer)
+        ANativeWindowBuffer* buffer)
 {
     FramebufferNativeWindow* self = getSelf(window);
     Mutex::Autolock _l(self->mutex);
@@ -249,7 +249,7 @@
 }
 
 int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, 
-        android_native_buffer_t* buffer)
+        ANativeWindowBuffer* buffer)
 {
     FramebufferNativeWindow* self = getSelf(window);
     Mutex::Autolock _l(self->mutex);
@@ -270,10 +270,10 @@
     return res;
 }
 
-int FramebufferNativeWindow::query(ANativeWindow* window,
+int FramebufferNativeWindow::query(const ANativeWindow* window,
         int what, int* value) 
 {
-    FramebufferNativeWindow* self = getSelf(window);
+    const FramebufferNativeWindow* self = getSelf(window);
     Mutex::Autolock _l(self->mutex);
     framebuffer_device_t* fb = self->fbDev;
     switch (what) {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 97312a6..54a3ffa 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -33,7 +33,7 @@
 namespace android {
 
 // ===========================================================================
-// Buffer and implementation of android_native_buffer_t
+// Buffer and implementation of ANativeWindowBuffer
 // ===========================================================================
 
 GraphicBuffer::GraphicBuffer()
@@ -77,7 +77,7 @@
     handle = inHandle;
 }
 
-GraphicBuffer::GraphicBuffer(android_native_buffer_t* buffer, bool keepOwnership)
+GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership)
     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
       mBufferMapper(GraphicBufferMapper::get()),
       mInitCheck(NO_ERROR), mIndex(-1), mWrappedBuffer(buffer)
@@ -119,9 +119,9 @@
     GraphicBufferAllocator::dumpToSystemLog();
 }
 
-android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
+ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
 {
-    return static_cast<android_native_buffer_t*>(
+    return static_cast<ANativeWindowBuffer*>(
             const_cast<GraphicBuffer*>(this));
 }
 
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 19d590a..1ba38a7 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -7,8 +7,12 @@
 
 //#define LOG_NDEBUG 0
 
+// Log debug messages about keymap probing.
 #define DEBUG_PROBE 0
 
+// Log debug messages about velocity tracking.
+#define DEBUG_VELOCITY 0
+
 #include <stdlib.h>
 #include <unistd.h>
 #include <ctype.h>
@@ -347,6 +351,40 @@
             "cannot contain more than %d axis values.", axis, int(MAX_AXES));
 }
 
+bool PointerCoords::operator==(const PointerCoords& other) const {
+    if (bits != other.bits) {
+        return false;
+    }
+    uint32_t count = __builtin_popcountll(bits);
+    for (uint32_t i = 0; i < count; i++) {
+        if (values[i] != other.values[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+void PointerCoords::copyFrom(const PointerCoords& other) {
+    bits = other.bits;
+    uint32_t count = __builtin_popcountll(bits);
+    for (uint32_t i = 0; i < count; i++) {
+        values[i] = other.values[i];
+    }
+}
+
+
+// --- PointerProperties ---
+
+bool PointerProperties::operator==(const PointerProperties& other) const {
+    return id == other.id
+            && toolType == other.toolType;
+}
+
+void PointerProperties::copyFrom(const PointerProperties& other) {
+    id = other.id;
+    toolType = other.toolType;
+}
+
 
 // --- MotionEvent ---
 
@@ -357,6 +395,7 @@
         int32_t flags,
         int32_t edgeFlags,
         int32_t metaState,
+        int32_t buttonState,
         float xOffset,
         float yOffset,
         float xPrecision,
@@ -364,20 +403,21 @@
         nsecs_t downTime,
         nsecs_t eventTime,
         size_t pointerCount,
-        const int32_t* pointerIds,
+        const PointerProperties* pointerProperties,
         const PointerCoords* pointerCoords) {
     InputEvent::initialize(deviceId, source);
     mAction = action;
     mFlags = flags;
     mEdgeFlags = edgeFlags;
     mMetaState = metaState;
+    mButtonState = buttonState;
     mXOffset = xOffset;
     mYOffset = yOffset;
     mXPrecision = xPrecision;
     mYPrecision = yPrecision;
     mDownTime = downTime;
-    mPointerIds.clear();
-    mPointerIds.appendArray(pointerIds, pointerCount);
+    mPointerProperties.clear();
+    mPointerProperties.appendArray(pointerProperties, pointerCount);
     mSampleEventTimes.clear();
     mSamplePointerCoords.clear();
     addSample(eventTime, pointerCoords);
@@ -389,12 +429,13 @@
     mFlags = other->mFlags;
     mEdgeFlags = other->mEdgeFlags;
     mMetaState = other->mMetaState;
+    mButtonState = other->mButtonState;
     mXOffset = other->mXOffset;
     mYOffset = other->mYOffset;
     mXPrecision = other->mXPrecision;
     mYPrecision = other->mYPrecision;
     mDownTime = other->mDownTime;
-    mPointerIds = other->mPointerIds;
+    mPointerProperties = other->mPointerProperties;
 
     if (keepHistory) {
         mSampleEventTimes = other->mSampleEventTimes;
@@ -458,6 +499,16 @@
     return value;
 }
 
+ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
+    size_t pointerCount = mPointerProperties.size();
+    for (size_t i = 0; i < pointerCount; i++) {
+        if (mPointerProperties.itemAt(i).id == pointerId) {
+            return i;
+        }
+    }
+    return -1;
+}
+
 void MotionEvent::offsetLocation(float xOffset, float yOffset) {
     mXOffset += xOffset;
     mYOffset += yOffset;
@@ -548,21 +599,25 @@
     mFlags = parcel->readInt32();
     mEdgeFlags = parcel->readInt32();
     mMetaState = parcel->readInt32();
+    mButtonState = parcel->readInt32();
     mXOffset = parcel->readFloat();
     mYOffset = parcel->readFloat();
     mXPrecision = parcel->readFloat();
     mYPrecision = parcel->readFloat();
     mDownTime = parcel->readInt64();
 
-    mPointerIds.clear();
-    mPointerIds.setCapacity(pointerCount);
+    mPointerProperties.clear();
+    mPointerProperties.setCapacity(pointerCount);
     mSampleEventTimes.clear();
     mSampleEventTimes.setCapacity(sampleCount);
     mSamplePointerCoords.clear();
     mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
 
     for (size_t i = 0; i < pointerCount; i++) {
-        mPointerIds.push(parcel->readInt32());
+        mPointerProperties.push();
+        PointerProperties& properties = mPointerProperties.editTop();
+        properties.id = parcel->readInt32();
+        properties.toolType = parcel->readInt32();
     }
 
     while (sampleCount-- > 0) {
@@ -579,7 +634,7 @@
 }
 
 status_t MotionEvent::writeToParcel(Parcel* parcel) const {
-    size_t pointerCount = mPointerIds.size();
+    size_t pointerCount = mPointerProperties.size();
     size_t sampleCount = mSampleEventTimes.size();
 
     parcel->writeInt32(pointerCount);
@@ -591,6 +646,7 @@
     parcel->writeInt32(mFlags);
     parcel->writeInt32(mEdgeFlags);
     parcel->writeInt32(mMetaState);
+    parcel->writeInt32(mButtonState);
     parcel->writeFloat(mXOffset);
     parcel->writeFloat(mYOffset);
     parcel->writeFloat(mXPrecision);
@@ -598,7 +654,9 @@
     parcel->writeInt64(mDownTime);
 
     for (size_t i = 0; i < pointerCount; i++) {
-        parcel->writeInt32(mPointerIds.itemAt(i));
+        const PointerProperties& properties = mPointerProperties.itemAt(i);
+        parcel->writeInt32(properties.id);
+        parcel->writeInt32(properties.toolType);
     }
 
     const PointerCoords* pc = mSamplePointerCoords.array();
@@ -633,6 +691,217 @@
 }
 
 
+// --- VelocityTracker ---
+
+VelocityTracker::VelocityTracker() {
+    clear();
+}
+
+void VelocityTracker::clear() {
+    mIndex = 0;
+    mMovements[0].idBits.clear();
+    mActivePointerId = -1;
+}
+
+void VelocityTracker::clearPointers(BitSet32 idBits) {
+    BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
+    mMovements[mIndex].idBits = remainingIdBits;
+
+    if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) {
+        mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1;
+    }
+}
+
+void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) {
+    if (++mIndex == HISTORY_SIZE) {
+        mIndex = 0;
+    }
+
+    while (idBits.count() > MAX_POINTERS) {
+        idBits.clearBit(idBits.lastMarkedBit());
+    }
+
+    Movement& movement = mMovements[mIndex];
+    movement.eventTime = eventTime;
+    movement.idBits = idBits;
+    uint32_t count = idBits.count();
+    for (uint32_t i = 0; i < count; i++) {
+        movement.positions[i] = positions[i];
+    }
+
+    if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) {
+        mActivePointerId = count != 0 ? idBits.firstMarkedBit() : -1;
+    }
+
+#if DEBUG_VELOCITY
+    LOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d",
+            eventTime, idBits.value, mActivePointerId);
+    for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) {
+        uint32_t id = iterBits.firstMarkedBit();
+        uint32_t index = idBits.getIndexOfBit(id);
+        iterBits.clearBit(id);
+        float vx, vy;
+        bool available = getVelocity(id, &vx, &vy);
+        if (available) {
+            LOGD("  %d: position (%0.3f, %0.3f), vx=%0.3f, vy=%0.3f, speed=%0.3f",
+                    id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy));
+        } else {
+            LOG_ASSERT(vx == 0 && vy == 0);
+            LOGD("  %d: position (%0.3f, %0.3f), velocity not available",
+                    id, positions[index].x, positions[index].y);
+        }
+    }
+#endif
+}
+
+void VelocityTracker::addMovement(const MotionEvent* event) {
+    int32_t actionMasked = event->getActionMasked();
+
+    switch (actionMasked) {
+    case AMOTION_EVENT_ACTION_DOWN:
+        // Clear all pointers on down before adding the new movement.
+        clear();
+        break;
+    case AMOTION_EVENT_ACTION_POINTER_DOWN: {
+        // Start a new movement trace for a pointer that just went down.
+        // We do this on down instead of on up because the client may want to query the
+        // final velocity for a pointer that just went up.
+        BitSet32 downIdBits;
+        downIdBits.markBit(event->getActionIndex());
+        clearPointers(downIdBits);
+        break;
+    }
+    case AMOTION_EVENT_ACTION_OUTSIDE:
+    case AMOTION_EVENT_ACTION_CANCEL:
+    case AMOTION_EVENT_ACTION_SCROLL:
+    case AMOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_POINTER_UP:
+        // Ignore these actions because they do not convey any new information about
+        // pointer movement.  We also want to preserve the last known velocity of the pointers.
+        // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
+        // of the pointers that went up.  ACTION_POINTER_UP does include the new position of
+        // pointers that remained down but we will also receive an ACTION_MOVE with this
+        // information if any of them actually moved.  Since we don't know how many pointers
+        // will be going up at once it makes sense to just wait for the following ACTION_MOVE
+        // before adding the movement.
+        return;
+    }
+
+    size_t pointerCount = event->getPointerCount();
+    if (pointerCount > MAX_POINTERS) {
+        pointerCount = MAX_POINTERS;
+    }
+
+    BitSet32 idBits;
+    for (size_t i = 0; i < pointerCount; i++) {
+        idBits.markBit(event->getPointerId(i));
+    }
+
+    nsecs_t eventTime;
+    Position positions[pointerCount];
+
+    size_t historySize = event->getHistorySize();
+    for (size_t h = 0; h < historySize; h++) {
+        eventTime = event->getHistoricalEventTime(h);
+        for (size_t i = 0; i < pointerCount; i++) {
+            positions[i].x = event->getHistoricalX(i, h);
+            positions[i].y = event->getHistoricalY(i, h);
+        }
+        addMovement(eventTime, idBits, positions);
+    }
+
+    eventTime = event->getEventTime();
+    for (size_t i = 0; i < pointerCount; i++) {
+        positions[i].x = event->getX(i);
+        positions[i].y = event->getY(i);
+    }
+    addMovement(eventTime, idBits, positions);
+}
+
+bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
+    const Movement& newestMovement = mMovements[mIndex];
+    if (newestMovement.idBits.hasBit(id)) {
+        // Find the oldest sample that contains the pointer and that is not older than MAX_AGE.
+        nsecs_t minTime = newestMovement.eventTime - MAX_AGE;
+        uint32_t oldestIndex = mIndex;
+        uint32_t numTouches = 1;
+        do {
+            uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
+            const Movement& nextOldestMovement = mMovements[nextOldestIndex];
+            if (!nextOldestMovement.idBits.hasBit(id)
+                    || nextOldestMovement.eventTime < minTime) {
+                break;
+            }
+            oldestIndex = nextOldestIndex;
+        } while (++numTouches < HISTORY_SIZE);
+
+        // Calculate an exponentially weighted moving average of the velocity estimate
+        // at different points in time measured relative to the oldest sample.
+        // This is essentially an IIR filter.  Newer samples are weighted more heavily
+        // than older samples.  Samples at equal time points are weighted more or less
+        // equally.
+        //
+        // One tricky problem is that the sample data may be poorly conditioned.
+        // Sometimes samples arrive very close together in time which can cause us to
+        // overestimate the velocity at that time point.  Most samples might be measured
+        // 16ms apart but some consecutive samples could be only 0.5sm apart because
+        // the hardware or driver reports them irregularly or in bursts.
+        float accumVx = 0;
+        float accumVy = 0;
+        uint32_t index = oldestIndex;
+        uint32_t samplesUsed = 0;
+        const Movement& oldestMovement = mMovements[oldestIndex];
+        const Position& oldestPosition =
+                oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)];
+        nsecs_t lastDuration = 0;
+
+        while (numTouches-- > 1) {
+            if (++index == HISTORY_SIZE) {
+                index = 0;
+            }
+            const Movement& movement = mMovements[index];
+            nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
+
+            // If the duration between samples is small, we may significantly overestimate
+            // the velocity.  Consequently, we impose a minimum duration constraint on the
+            // samples that we include in the calculation.
+            if (duration >= MIN_DURATION) {
+                const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)];
+                float scale = 1000000000.0f / duration; // one over time delta in seconds
+                float vx = (position.x - oldestPosition.x) * scale;
+                float vy = (position.y - oldestPosition.y) * scale;
+
+                accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
+                accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
+
+                lastDuration = duration;
+                samplesUsed += 1;
+            }
+        }
+
+        // Make sure we used at least one sample.
+        if (samplesUsed != 0) {
+            // Scale the velocity linearly if the window of samples is small.
+            nsecs_t totalDuration = newestMovement.eventTime - oldestMovement.eventTime;
+            if (totalDuration < MIN_WINDOW) {
+                float scale = float(totalDuration) / float(MIN_WINDOW);
+                accumVx *= scale;
+                accumVy *= scale;
+            }
+
+            *outVx = accumVx;
+            *outVy = accumVy;
+            return true;
+        }
+    }
+
+    // No data available for this pointer.
+    *outVx = 0;
+    *outVy = 0;
+    return false;
+}
+
+
 // --- InputDeviceInfo ---
 
 InputDeviceInfo::InputDeviceInfo() {
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index 5c57a76..ffdfe66 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -27,8 +27,14 @@
 
 namespace android {
 
+#define ROUND_UP(value, boundary) (((value) + (boundary) - 1) & ~((boundary) - 1))
+#define MIN_HISTORY_DEPTH 20
+
 // Must be at least sizeof(InputMessage) + sufficient space for pointer data
-static const int DEFAULT_MESSAGE_BUFFER_SIZE = 16384;
+static const int DEFAULT_MESSAGE_BUFFER_SIZE = ROUND_UP(
+        sizeof(InputMessage) + MIN_HISTORY_DEPTH
+                * (sizeof(InputMessage::SampleData) + MAX_POINTERS * sizeof(PointerCoords)),
+        4096);
 
 // Signal sent by the producer to the consumer to inform it that a new message is
 // available to be consumed in the shared memory buffer.
@@ -360,6 +366,7 @@
         int32_t flags,
         int32_t edgeFlags,
         int32_t metaState,
+        int32_t buttonState,
         float xOffset,
         float yOffset,
         float xPrecision,
@@ -367,16 +374,17 @@
         nsecs_t downTime,
         nsecs_t eventTime,
         size_t pointerCount,
-        const int32_t* pointerIds,
+        const PointerProperties* pointerProperties,
         const PointerCoords* pointerCoords) {
 #if DEBUG_TRANSPORT_ACTIONS
     LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
-            "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, "
+            "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
+            "xOffset=%f, yOffset=%f, "
             "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
             "pointerCount=%d",
             mChannel->getName().string(),
-            deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
-            xPrecision, yPrecision, downTime, eventTime, pointerCount);
+            deviceId, source, action, flags, edgeFlags, metaState, buttonState,
+            xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
 #endif
 
     if (pointerCount > MAX_POINTERS || pointerCount < 1) {
@@ -394,6 +402,7 @@
     mSharedMessage->motion.flags = flags;
     mSharedMessage->motion.edgeFlags = edgeFlags;
     mSharedMessage->motion.metaState = metaState;
+    mSharedMessage->motion.buttonState = buttonState;
     mSharedMessage->motion.xOffset = xOffset;
     mSharedMessage->motion.yOffset = yOffset;
     mSharedMessage->motion.xPrecision = xPrecision;
@@ -405,8 +414,8 @@
     mSharedMessage->motion.sampleData[0].eventTime = eventTime;
 
     for (size_t i = 0; i < pointerCount; i++) {
-        mSharedMessage->motion.pointerIds[i] = pointerIds[i];
-        mSharedMessage->motion.sampleData[0].coords[i] = pointerCoords[i];
+        mSharedMessage->motion.pointerProperties[i].copyFrom(pointerProperties[i]);
+        mSharedMessage->motion.sampleData[0].coords[i].copyFrom(pointerCoords[i]);
     }
 
     // Cache essential information about the motion event to ensure that a malicious consumer
@@ -475,7 +484,7 @@
 
     mMotionEventSampleDataTail->eventTime = eventTime;
     for (size_t i = 0; i < mMotionEventPointerCount; i++) {
-        mMotionEventSampleDataTail->coords[i] = pointerCoords[i];
+        mMotionEventSampleDataTail->coords[i].copyFrom(pointerCoords[i]);
     }
     mMotionEventSampleDataTail = newTail;
 
@@ -688,6 +697,7 @@
             mSharedMessage->motion.flags,
             mSharedMessage->motion.edgeFlags,
             mSharedMessage->motion.metaState,
+            mSharedMessage->motion.buttonState,
             mSharedMessage->motion.xOffset,
             mSharedMessage->motion.yOffset,
             mSharedMessage->motion.xPrecision,
@@ -695,7 +705,7 @@
             mSharedMessage->motion.downTime,
             mSharedMessage->motion.sampleData[0].eventTime,
             mSharedMessage->motion.pointerCount,
-            mSharedMessage->motion.pointerIds,
+            mSharedMessage->motion.pointerProperties,
             mSharedMessage->motion.sampleData[0].coords);
 
     size_t sampleCount = mSharedMessage->motion.sampleCount;
diff --git a/libs/ui/tests/InputEvent_test.cpp b/libs/ui/tests/InputEvent_test.cpp
index b77489e..e48d5b7 100644
--- a/libs/ui/tests/InputEvent_test.cpp
+++ b/libs/ui/tests/InputEvent_test.cpp
@@ -232,7 +232,14 @@
 const float MotionEventTest::Y_OFFSET = 1.1f;
 
 void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
-    int32_t pointerIds[] = { 1, 2 };
+    PointerProperties pointerProperties[2];
+    pointerProperties[0].clear();
+    pointerProperties[0].id = 1;
+    pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+    pointerProperties[1].clear();
+    pointerProperties[1].id = 2;
+    pointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+
     PointerCoords pointerCoords[2];
     pointerCoords[0].clear();
     pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 10);
@@ -256,10 +263,10 @@
     pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
     event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
             AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
-            AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON,
+            AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
             X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
             ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
-            2, pointerIds, pointerCoords);
+            2, pointerProperties, pointerCoords);
 
     pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
     pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
@@ -311,6 +318,7 @@
     ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
     ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
     ASSERT_EQ(AMETA_ALT_ON, event->getMetaState());
+    ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState());
     ASSERT_EQ(X_OFFSET, event->getXOffset());
     ASSERT_EQ(Y_OFFSET, event->getYOffset());
     ASSERT_EQ(2.0f, event->getXPrecision());
@@ -319,7 +327,9 @@
 
     ASSERT_EQ(2U, event->getPointerCount());
     ASSERT_EQ(1, event->getPointerId(0));
+    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, event->getToolType(0));
     ASSERT_EQ(2, event->getPointerId(1));
+    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, event->getToolType(1));
 
     ASSERT_EQ(2U, event->getHistorySize());
 
@@ -534,19 +544,20 @@
     const float ROTATION = ARC * 2;
 
     const size_t pointerCount = 11;
-    int pointerIds[pointerCount];
+    PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
     for (size_t i = 0; i < pointerCount; i++) {
         float angle = float(i * ARC * PI_180);
-        pointerIds[i] = i;
+        pointerProperties[i].clear();
+        pointerProperties[i].id = i;
         pointerCoords[i].clear();
         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, sinf(angle) * RADIUS + 3);
         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, -cosf(angle) * RADIUS + 2);
         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
     }
     MotionEvent event;
-    event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+    event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
     float originalRawX = 0 + 3;
     float originalRawY = -RADIUS + 2;
 
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index 6e18a4f..fcc4cad 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -156,13 +156,19 @@
     const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
     const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
     const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
+    const int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
     const float xOffset = -10;
     const float yOffset = -20;
     const float xPrecision = 0.25;
     const float yPrecision = 0.5;
     const nsecs_t downTime = 3;
     const size_t pointerCount = 3;
-    const int32_t pointerIds[pointerCount] = { 2, 0, 1 };
+    PointerProperties pointerProperties[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerProperties[i].id = (i + 2) % pointerCount;
+        pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+    }
 
     Vector<nsecs_t> sampleEventTimes;
     Vector<PointerCoords> samplePointerCoords;
@@ -186,8 +192,9 @@
     }
 
     status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
-            metaState, xOffset, yOffset, xPrecision, yPrecision,
-            downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
+            metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
+            downTime, sampleEventTimes[0], pointerCount,
+            pointerProperties, samplePointerCoords.array());
     ASSERT_EQ(OK, status)
             << "publisher publishMotionEvent should return OK";
 
@@ -234,6 +241,7 @@
     EXPECT_EQ(flags, motionEvent->getFlags());
     EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
     EXPECT_EQ(metaState, motionEvent->getMetaState());
+    EXPECT_EQ(buttonState, motionEvent->getButtonState());
     EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
     EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
     EXPECT_EQ(downTime, motionEvent->getDownTime());
@@ -243,7 +251,8 @@
 
     for (size_t i = 0; i < pointerCount; i++) {
         SCOPED_TRACE(i);
-        EXPECT_EQ(pointerIds[i], motionEvent->getPointerId(i));
+        EXPECT_EQ(pointerProperties[i].id, motionEvent->getPointerId(i));
+        EXPECT_EQ(pointerProperties[i].toolType, motionEvent->getToolType(i));
     }
 
     for (size_t sampleIndex = 0; sampleIndex < lastSampleIndex; sampleIndex++) {
@@ -352,17 +361,20 @@
     ASSERT_NO_FATAL_FAILURE(Initialize());
 
     const size_t pointerCount = 1;
-    int32_t pointerIds[pointerCount] = { 0 };
+    PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
-    pointerCoords[0].clear();
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerCoords[i].clear();
+    }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerIds, pointerCoords);
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(OK, status)
             << "publisher publishMotionEvent should return OK";
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerIds, pointerCoords);
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(INVALID_OPERATION, status)
             << "publisher publishMotionEvent should return INVALID_OPERATION because ";
                     "the publisher was not reset";
@@ -373,11 +385,11 @@
     ASSERT_NO_FATAL_FAILURE(Initialize());
 
     const size_t pointerCount = 0;
-    int32_t pointerIds[pointerCount];
+    PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerIds, pointerCoords);
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
@@ -387,11 +399,15 @@
     ASSERT_NO_FATAL_FAILURE(Initialize());
 
     const size_t pointerCount = MAX_POINTERS + 1;
-    int32_t pointerIds[pointerCount];
+    PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerCoords[i].clear();
+    }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            pointerCount, pointerIds, pointerCoords);
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
 }
@@ -432,11 +448,15 @@
     ASSERT_NO_FATAL_FAILURE(Initialize());
 
     const size_t pointerCount = MAX_POINTERS;
-    int32_t pointerIds[pointerCount];
+    PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerCoords[i].clear();
+    }
 
     status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(OK, status);
 
     status = mPublisher->appendMotionSample(0, pointerCoords);
@@ -449,11 +469,15 @@
     ASSERT_NO_FATAL_FAILURE(Initialize());
 
     const size_t pointerCount = MAX_POINTERS;
-    int32_t pointerIds[pointerCount];
+    PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerCoords[i].clear();
+    }
 
     status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(OK, status);
 
     status = mPublisher->sendDispatchSignal();
@@ -476,11 +500,15 @@
     ASSERT_NO_FATAL_FAILURE(Initialize());
 
     const size_t pointerCount = MAX_POINTERS;
-    int32_t pointerIds[pointerCount];
+    PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerCoords[i].clear();
+    }
 
     status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(OK, status);
 
     for (int count = 1;; count++) {
diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp
index 0b4d1ac..22034c5 100644
--- a/libs/utils/AssetManager.cpp
+++ b/libs/utils/AssetManager.cpp
@@ -36,6 +36,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <assert.h>
+#include <strings.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -1998,4 +1999,3 @@
 
     return mZipPath.size()-1;
 }
-
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index adb3174..f963058 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -20,12 +20,15 @@
 #include <utils/ByteOrder.h>
 
 #include <stdio.h>
+#include <string.h>
 #include <unistd.h>
 
 #include <cutils/log.h>
 
 namespace android {
 
+static const bool DEBUG = false;
+
 /*
  * File Format (v1):
  *
@@ -75,6 +78,7 @@
     paddingSize = padding_extra(n);
     if (paddingSize > 0) {
         uint32_t padding = 0xbcbcbcbc;
+        if (DEBUG) LOGI("writing %d padding bytes for %d", paddingSize, n);
         amt = write(m_fd, &padding, paddingSize);
         if (amt != paddingSize) {
             m_status = errno;
@@ -107,8 +111,8 @@
     } else {
         k = key;
     }
-    if (false) {
-        LOGD("Writing entity: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(), key.string(),
+    if (DEBUG) {
+        LOGD("Writing header: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(), key.string(),
                 dataSize);
     }
 
@@ -121,6 +125,7 @@
     header.keyLen = tolel(keyLen);
     header.dataSize = tolel(dataSize);
 
+    if (DEBUG) LOGI("writing entity header, %d bytes", sizeof(entity_header_v1));
     amt = write(m_fd, &header, sizeof(entity_header_v1));
     if (amt != sizeof(entity_header_v1)) {
         m_status = errno;
@@ -128,6 +133,7 @@
     }
     m_pos += amt;
 
+    if (DEBUG) LOGI("writing entity header key, %d bytes", keyLen+1);
     amt = write(m_fd, k.string(), keyLen+1);
     if (amt != keyLen+1) {
         m_status = errno;
@@ -145,7 +151,12 @@
 status_t
 BackupDataWriter::WriteEntityData(const void* data, size_t size)
 {
+    if (DEBUG) LOGD("Writing data: size=%lu", (unsigned long) size);
+
     if (m_status != NO_ERROR) {
+        if (DEBUG) {
+            LOGD("Not writing data - stream in error state %d (%s)", m_status, strerror(m_status));
+        }
         return m_status;
     }
 
@@ -155,6 +166,7 @@
     ssize_t amt = write(m_fd, data, size);
     if (amt != (ssize_t)size) {
         m_status = errno;
+        if (DEBUG) LOGD("write returned error %d (%s)", m_status, strerror(m_status));
         return m_status;
     }
     m_pos += amt;
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
index 4ad9b51..e15875f 100644
--- a/libs/utils/BackupHelpers.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -442,6 +442,267 @@
     return 0;
 }
 
+// Utility function, equivalent to stpcpy(): perform a strcpy, but instead of
+// returning the initial dest, return a pointer to the trailing NUL.
+static char* strcpy_ptr(char* dest, const char* str) {
+    if (dest && str) {
+        while ((*dest = *str) != 0) {
+            dest++;
+            str++;
+        }
+    }
+    return dest;
+}
+
+static void calc_tar_checksum(char* buf) {
+    // [ 148 :   8 ] checksum -- to be calculated with this field as space chars
+    memset(buf + 148, ' ', 8);
+
+    uint16_t sum = 0;
+    for (uint8_t* p = (uint8_t*) buf; p < ((uint8_t*)buf) + 512; p++) {
+        sum += *p;
+    }
+
+    // Now write the real checksum value:
+    // [ 148 :   8 ]  checksum: 6 octal digits [leading zeroes], NUL, SPC
+    sprintf(buf + 148, "%06o", sum); // the trailing space is already in place
+}
+
+// Returns number of bytes written
+static int write_pax_header_entry(char* buf, const char* key, const char* value) {
+    // start with the size of "1 key=value\n"
+    int len = strlen(key) + strlen(value) + 4;
+    if (len > 9) len++;
+    if (len > 99) len++;
+    if (len > 999) len++;
+    // since PATH_MAX is 4096 we don't expect to have to generate any single
+    // header entry longer than 9999 characters
+
+    return sprintf(buf, "%d %s=%s\n", len, key, value);
+}
+
+int write_tarfile(const String8& packageName, const String8& domain,
+        const String8& rootpath, const String8& filepath, BackupDataWriter* writer)
+{
+    // In the output stream everything is stored relative to the root
+    const char* relstart = filepath.string() + rootpath.length();
+    if (*relstart == '/') relstart++;     // won't be true when path == rootpath
+    String8 relpath(relstart);
+
+    // If relpath is empty, it means this is the top of one of the standard named
+    // domain directories, so we should just skip it
+    if (relpath.length() == 0) {
+        return 0;
+    }
+
+    // Too long a name for the ustar format?
+    //    "apps/" + packagename + '/' + domainpath < 155 chars
+    //    relpath < 100 chars
+    bool needExtended = false;
+    if ((5 + packageName.length() + 1 + domain.length() >= 155) || (relpath.length() >= 100)) {
+        needExtended = true;
+    }
+
+    int err = 0;
+    struct stat64 s;
+    if (lstat64(filepath.string(), &s) != 0) {
+        err = errno;
+        LOGE("Error %d (%s) from lstat64(%s)", err, strerror(err), filepath.string());
+        return err;
+    }
+
+    String8 fullname;   // for pax later on
+    String8 prefix;
+
+    const int isdir = S_ISDIR(s.st_mode);
+
+    // !!! TODO: use mmap when possible to avoid churning the buffer cache
+    // !!! TODO: this will break with symlinks; need to use readlink(2)
+    int fd = open(filepath.string(), O_RDONLY);
+    if (fd < 0) {
+        err = errno;
+        LOGE("Error %d (%s) from open(%s)", err, strerror(err), filepath.string());
+        return err;
+    }
+
+    // read/write up to this much at a time.
+    const size_t BUFSIZE = 32 * 1024;
+    char* buf = new char[BUFSIZE];
+    char* paxHeader = buf + 512;    // use a different chunk of it as separate scratch
+    char* paxData = buf + 1024;
+
+    if (buf == NULL) {
+        LOGE("Out of mem allocating transfer buffer");
+        err = ENOMEM;
+        goto cleanup;
+    }
+
+    // Good to go -- first construct the standard tar header at the start of the buffer
+    memset(buf, 0, BUFSIZE);
+
+    // Magic fields for the ustar file format
+    strcat(buf + 257, "ustar");
+    strcat(buf + 263, "00");
+
+    // [ 265 : 32 ] user name, ignored on restore
+    // [ 297 : 32 ] group name, ignored on restore
+
+    // [ 100 :   8 ] file mode
+    snprintf(buf + 100, 8, "%06o ", s.st_mode & ~S_IFMT);
+
+    // [ 108 :   8 ] uid -- ignored in Android format; uids are remapped at restore time
+    // [ 116 :   8 ] gid -- ignored in Android format
+    snprintf(buf + 108, 8, "0%lo", s.st_uid);
+    snprintf(buf + 116, 8, "0%lo", s.st_gid);
+
+    // [ 124 :  12 ] file size in bytes
+    if (s.st_size > 077777777777LL) {
+        // very large files need a pax extended size header
+        needExtended = true;
+    }
+    snprintf(buf + 124, 12, "%011llo", (isdir) ? 0LL : s.st_size);
+
+    // [ 136 :  12 ] last mod time as a UTC time_t
+    snprintf(buf + 136, 12, "%0lo", s.st_mtime);
+
+    // [ 156 :   1 ] link/file type
+    uint8_t type;
+    if (isdir) {
+        type = '5';     // tar magic: '5' == directory
+    } else if (S_ISREG(s.st_mode)) {
+        type = '0';     // tar magic: '0' == normal file
+    } else {
+        LOGW("Error: unknown file mode 0%o [%s]", s.st_mode, filepath.string());
+        goto cleanup;
+    }
+    buf[156] = type;
+
+    // [ 157 : 100 ] name of linked file [not implemented]
+
+    {
+        // Prefix and main relative path.  Path lengths have been preflighted.
+        if (packageName.length() > 0) {
+            prefix = "apps/";
+            prefix += packageName;
+        }
+        if (domain.length() > 0) {
+            prefix.appendPath(domain);
+        }
+
+        // pax extended means we don't put in a prefix field, and put a different
+        // string in the basic name field.  We can also construct the full path name
+        // out of the substrings we've now built.
+        fullname = prefix;
+        fullname.appendPath(relpath);
+
+        // ustar:
+        //    [   0 : 100 ]; file name/path
+        //    [ 345 : 155 ] filename path prefix
+        // We only use the prefix area if fullname won't fit in the path
+        if (fullname.length() > 100) {
+            strncpy(buf, relpath.string(), 100);
+            strncpy(buf + 345, prefix.string(), 155);
+        } else {
+            strncpy(buf, fullname.string(), 100);
+        }
+    }
+
+    // [ 329 : 8 ] and [ 337 : 8 ] devmajor/devminor, not used
+
+    LOGI("   Name: %s", fullname.string());
+
+    // If we're using a pax extended header, build & write that here; lengths are
+    // already preflighted
+    if (needExtended) {
+        char sizeStr[32];   // big enough for a 64-bit unsigned value in decimal
+        char* p = paxData;
+
+        // construct the pax extended header data block
+        memset(paxData, 0, BUFSIZE - (paxData - buf));
+        int len;
+
+        // size header -- calc len in digits by actually rendering the number
+        // to a string - brute force but simple
+        snprintf(sizeStr, sizeof(sizeStr), "%lld", s.st_size);
+        p += write_pax_header_entry(p, "size", sizeStr);
+
+        // fullname was generated above with the ustar paths
+        p += write_pax_header_entry(p, "path", fullname.string());
+
+        // Now we know how big the pax data is
+        int paxLen = p - paxData;
+
+        // Now build the pax *header* templated on the ustar header
+        memcpy(paxHeader, buf, 512);
+
+        String8 leaf = fullname.getPathLeaf();
+        memset(paxHeader, 0, 100);                  // rewrite the name area
+        snprintf(paxHeader, 100, "PaxHeader/%s", leaf.string());
+        memset(paxHeader + 345, 0, 155);            // rewrite the prefix area
+        strncpy(paxHeader + 345, prefix.string(), 155);
+
+        paxHeader[156] = 'x';                       // mark it as a pax extended header
+
+        // [ 124 :  12 ] size of pax extended header data
+        memset(paxHeader + 124, 0, 12);
+        snprintf(paxHeader + 124, 12, "%011o", p - paxData);
+
+        // Checksum and write the pax block header
+        calc_tar_checksum(paxHeader);
+        writer->WriteEntityData(paxHeader, 512);
+
+        // Now write the pax data itself
+        int paxblocks = (paxLen + 511) / 512;
+        writer->WriteEntityData(paxData, 512 * paxblocks);
+    }
+
+    // Checksum and write the 512-byte ustar file header block to the output
+    calc_tar_checksum(buf);
+    writer->WriteEntityData(buf, 512);
+
+    // Now write the file data itself, for real files.  We honor tar's convention that
+    // only full 512-byte blocks are sent to write().
+    if (!isdir) {
+        off64_t toWrite = s.st_size;
+        while (toWrite > 0) {
+            size_t toRead = (toWrite < BUFSIZE) ? toWrite : BUFSIZE;
+            ssize_t nRead = read(fd, buf, toRead);
+            if (nRead < 0) {
+                err = errno;
+                LOGE("Unable to read file [%s], err=%d (%s)", filepath.string(),
+                        err, strerror(err));
+                break;
+            } else if (nRead == 0) {
+                LOGE("EOF but expect %lld more bytes in [%s]", (long long) toWrite,
+                        filepath.string());
+                err = EIO;
+                break;
+            }
+
+            // At EOF we might have a short block; NUL-pad that to a 512-byte multiple.  This
+            // depends on the OS guarantee that for ordinary files, read() will never return
+            // less than the number of bytes requested.
+            ssize_t partial = (nRead+512) % 512;
+            if (partial > 0) {
+                ssize_t remainder = 512 - partial;
+                memset(buf + nRead, 0, remainder);
+                nRead += remainder;
+            }
+            writer->WriteEntityData(buf, nRead);
+            toWrite -= nRead;
+        }
+    }
+
+cleanup:
+    delete [] buf;
+done:
+    close(fd);
+    return err;
+}
+// end tarfile
+
+
+
 #define RESTORE_BUF_SIZE (8*1024)
 
 RestoreHelperBase::RestoreHelperBase()
diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp
index 18f858b..b54fb9d 100644
--- a/libs/utils/Looper.cpp
+++ b/libs/utils/Looper.cpp
@@ -218,14 +218,10 @@
     // Adjust the timeout based on when the next message is due.
     if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-        if (mNextMessageUptime <= now) {
-            timeoutMillis = 0;
-        } else {
-            uint64_t delay = (mNextMessageUptime - now + 999999LL) / 1000000LL;
-            if (delay < INT_MAX
-                    && (timeoutMillis < 0 || int(delay) < timeoutMillis)) {
-                timeoutMillis = int(delay);
-            }
+        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
+        if (messageTimeoutMillis >= 0
+                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
+            timeoutMillis = messageTimeoutMillis;
         }
 #if DEBUG_POLL_AND_WAKE
         LOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
@@ -444,12 +440,11 @@
                 return result;
             }
 
-            nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC);
-            if (timeoutNanos <= 0) {
+            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+            timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
+            if (timeoutMillis == 0) {
                 return ALOOPER_POLL_TIMEOUT;
             }
-
-            timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL));
         }
     }
 }
@@ -667,7 +662,8 @@
 #endif
 
 void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
-    sendMessageAtTime(LLONG_MIN, handler, message);
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    sendMessageAtTime(now, handler, message);
 }
 
 void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index 2034486..dd0052a 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -345,6 +345,10 @@
     const_cast<RefBase*>(this)->onFirstRef();
 }
 
+void RefBase::destroy() const {
+    delete this;
+}
+
 void RefBase::decStrong(const void* id) const
 {
     weakref_impl* const refs = mRefs;
@@ -357,7 +361,7 @@
     if (c == 1) {
         const_cast<RefBase*>(this)->onLastStrongRef(id);
         if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
-            delete this;
+            destroy();
         }
     }
     refs->decWeak(id);
@@ -415,7 +419,8 @@
     
     if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
         if (impl->mStrong == INITIAL_STRONG_VALUE)
-            delete impl->mBase;
+            if (impl->mBase)
+                impl->mBase->destroy();
         else {
             // LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
             delete impl;
@@ -423,7 +428,8 @@
     } else {
         impl->mBase->onLastWeakRef(id);
         if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
-            delete impl->mBase;
+            if (impl->mBase)
+                impl->mBase->destroy();
         }
     }
 }
diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp
index 784f035..64a29f5 100644
--- a/libs/utils/Timers.cpp
+++ b/libs/utils/Timers.cpp
@@ -26,6 +26,7 @@
 #include <sys/time.h>
 #include <time.h>
 #include <errno.h>
+#include <limits.h>
 
 #ifdef HAVE_WIN32_THREADS
 #include <windows.h>
@@ -53,6 +54,23 @@
 #endif
 }
 
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime)
+{
+    int timeoutDelayMillis;
+    if (timeoutTime > referenceTime) {
+        uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
+        if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
+            timeoutDelayMillis = -1;
+        } else {
+            timeoutDelayMillis = (timeoutDelay + 999999LL) / 1000000LL;
+        }
+    } else {
+        timeoutDelayMillis = 0;
+    }
+    return timeoutDelayMillis;
+}
+
+
 /*
  * ===========================================================================
  *      DurationTimer
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 1ffcd56..1123e16 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -225,7 +225,7 @@
 
 #ifndef EGL_ANDROID_image_native_buffer
 #define EGL_ANDROID_image_native_buffer 1
-struct android_native_buffer_t;
+struct ANativeWindowBuffer;
 #define EGL_NATIVE_BUFFER_ANDROID       0x3140  /* eglCreateImageKHR target */
 #endif
 
diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp
index bbb82fc..022de09 100644
--- a/opengl/libagl/TextureObjectManager.cpp
+++ b/opengl/libagl/TextureObjectManager.cpp
@@ -145,7 +145,7 @@
     return NO_ERROR;
 }
 
-status_t EGLTextureObject::setImage(android_native_buffer_t* native_buffer)
+status_t EGLTextureObject::setImage(ANativeWindowBuffer* native_buffer)
 {
     GGLSurface sur;
     sur.version = sizeof(GGLSurface);
diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h
index 70e3bef..de9e03e 100644
--- a/opengl/libagl/TextureObjectManager.h
+++ b/opengl/libagl/TextureObjectManager.h
@@ -48,7 +48,7 @@
                    ~EGLTextureObject();
 
     status_t    setSurface(GGLSurface const* s);
-    status_t    setImage(android_native_buffer_t* buffer);
+    status_t    setImage(ANativeWindowBuffer* buffer);
     void        setImageBits(void* vaddr) { surface.data = (GGLubyte*)vaddr; }
 
     status_t            reallocate(GLint level,
@@ -80,7 +80,7 @@
     GLint               crop_rect[4];
     GLint               generate_mipmap;
     GLint               direct;
-    android_native_buffer_t* buffer;
+    ANativeWindowBuffer* buffer;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index a1cb23a..03db8d7 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -41,8 +41,6 @@
 
 #include <private/ui/android_natives_priv.h>
 
-#include <hardware/copybit.h>
-
 #include "context.h"
 #include "state.h"
 #include "texture.h"
@@ -232,13 +230,12 @@
     virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
     
 private:
-    status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
-    status_t unlock(android_native_buffer_t* buf);
+    status_t lock(ANativeWindowBuffer* buf, int usage, void** vaddr);
+    status_t unlock(ANativeWindowBuffer* buf);
     ANativeWindow*   nativeWindow;
-    android_native_buffer_t*   buffer;
-    android_native_buffer_t*   previousBuffer;
+    ANativeWindowBuffer*   buffer;
+    ANativeWindowBuffer*   previousBuffer;
     gralloc_module_t const*    module;
-    copybit_device_t*          blitengine;
     int width;
     int height;
     void* bits;
@@ -324,27 +321,9 @@
         ssize_t count;
     };
     
-    struct region_iterator : public copybit_region_t {
-        region_iterator(const Region& region)
-            : b(region.begin()), e(region.end()) {
-            this->next = iterate;
-        }
-    private:
-        static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
-            region_iterator const* me = static_cast<region_iterator const*>(self);
-            if (me->b != me->e) {
-                *reinterpret_cast<Rect*>(rect) = *me->b++;
-                return 1;
-            }
-            return 0;
-        }
-        mutable Region::const_iterator b;
-        Region::const_iterator const e;
-    };
-
     void copyBlt(
-            android_native_buffer_t* dst, void* dst_vaddr,
-            android_native_buffer_t* src, void const* src_vaddr,
+            ANativeWindowBuffer* dst, void* dst_vaddr,
+            ANativeWindowBuffer* src, void const* src_vaddr,
             const Region& clip);
 
     Rect dirtyRegion;
@@ -357,16 +336,12 @@
         ANativeWindow* window)
     : egl_surface_t(dpy, config, depthFormat), 
     nativeWindow(window), buffer(0), previousBuffer(0), module(0),
-    blitengine(0), bits(NULL)
+    bits(NULL)
 {
     hw_module_t const* pModule;
     hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
     module = reinterpret_cast<gralloc_module_t const*>(pModule);
 
-    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) {
-        copybit_open(pModule, &blitengine);
-    }
-
     pixelFormatTable = gglGetPixelFormatTable();
     
     // keep a reference on the window
@@ -383,9 +358,6 @@
         previousBuffer->common.decRef(&previousBuffer->common); 
     }
     nativeWindow->common.decRef(&nativeWindow->common);
-    if (blitengine) {
-        copybit_close(blitengine);
-    }
 }
 
 EGLBoolean egl_window_surface_v2_t::connect() 
@@ -447,7 +419,7 @@
 }
 
 status_t egl_window_surface_v2_t::lock(
-        android_native_buffer_t* buf, int usage, void** vaddr)
+        ANativeWindowBuffer* buf, int usage, void** vaddr)
 {
     int err;
 
@@ -457,7 +429,7 @@
     return err;
 }
 
-status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
+status_t egl_window_surface_v2_t::unlock(ANativeWindowBuffer* buf)
 {
     if (!buf) return BAD_VALUE;
     int err = NO_ERROR;
@@ -468,67 +440,39 @@
 }
 
 void egl_window_surface_v2_t::copyBlt(
-        android_native_buffer_t* dst, void* dst_vaddr,
-        android_native_buffer_t* src, void const* src_vaddr,
+        ANativeWindowBuffer* dst, void* dst_vaddr,
+        ANativeWindowBuffer* src, void const* src_vaddr,
         const Region& clip)
 {
-    // FIXME: use copybit if possible
     // NOTE: dst and src must be the same format
     
-    status_t err = NO_ERROR;
-    copybit_device_t* const copybit = blitengine;
-    if (copybit)  {
-        copybit_image_t simg;
-        simg.w = src->stride;
-        simg.h = src->height;
-        simg.format = src->format;
-        simg.handle = const_cast<native_handle_t*>(src->handle);
+    Region::const_iterator cur = clip.begin();
+    Region::const_iterator end = clip.end();
 
-        copybit_image_t dimg;
-        dimg.w = dst->stride;
-        dimg.h = dst->height;
-        dimg.format = dst->format;
-        dimg.handle = const_cast<native_handle_t*>(dst->handle);
-        
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
-        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
-        region_iterator it(clip);
-        err = copybit->blit(copybit, &dimg, &simg, &it);
-        if (err != NO_ERROR) {
-            LOGE("copybit failed (%s)", strerror(err));
+    const size_t bpp = pixelFormatTable[src->format].size;
+    const size_t dbpr = dst->stride * bpp;
+    const size_t sbpr = src->stride * bpp;
+
+    uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
+    uint8_t       * const dst_bits = (uint8_t       *)dst_vaddr;
+
+    while (cur != end) {
+        const Rect& r(*cur++);
+        ssize_t w = r.right - r.left;
+        ssize_t h = r.bottom - r.top;
+        if (w <= 0 || h<=0) continue;
+        size_t size = w * bpp;
+        uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+        uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
+        if (dbpr==sbpr && size==sbpr) {
+            size *= h;
+            h = 1;
         }
-    }
-
-    if (!copybit || err) {
-        Region::const_iterator cur = clip.begin();
-        Region::const_iterator end = clip.end();
-        
-        const size_t bpp = pixelFormatTable[src->format].size;
-        const size_t dbpr = dst->stride * bpp;
-        const size_t sbpr = src->stride * bpp;
-
-        uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
-        uint8_t       * const dst_bits = (uint8_t       *)dst_vaddr;
-
-        while (cur != end) {
-            const Rect& r(*cur++);
-            ssize_t w = r.right - r.left;
-            ssize_t h = r.bottom - r.top;
-            if (w <= 0 || h<=0) continue;
-            size_t size = w * bpp;
-            uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
-            uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
-            if (dbpr==sbpr && size==sbpr) {
-                size *= h;
-                h = 1;
-            }
-            do {
-                memcpy(d, s, size);
-                d += dbpr;
-                s += sbpr;
-            } while (--h > 0);
-        }
+        do {
+            memcpy(d, s, size);
+            d += dbpr;
+            s += sbpr;
+        } while (--h > 0);
     }
 }
 
@@ -2063,12 +2007,12 @@
         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
     }
 
-    android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
+    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)buffer;
 
     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
 
-    if (native_buffer->common.version != sizeof(android_native_buffer_t))
+    if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
 
     switch (native_buffer->format) {
@@ -2094,12 +2038,12 @@
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     }
 
-    android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
+    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)img;
 
     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
 
-    if (native_buffer->common.version != sizeof(android_native_buffer_t))
+    if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
 
     native_buffer->common.decRef(&native_buffer->common);
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index eb96895..8eb17c4 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -126,7 +126,7 @@
     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
         if (c->rasterizer.state.texture[i].enable) {
             texture_unit_t& u(c->textures.tmu[i]);
-            android_native_buffer_t* native_buffer = u.texture->buffer;
+            ANativeWindowBuffer* native_buffer = u.texture->buffer;
             if (native_buffer) {
                 c->rasterizer.procs.activeTexture(c, i);
                 hw_module_t const* pModule;
@@ -154,7 +154,7 @@
     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
         if (c->rasterizer.state.texture[i].enable) {
             texture_unit_t& u(c->textures.tmu[i]);
-            android_native_buffer_t* native_buffer = u.texture->buffer;
+            ANativeWindowBuffer* native_buffer = u.texture->buffer;
             if (native_buffer) {
                 c->rasterizer.procs.activeTexture(c, i);
                 hw_module_t const* pModule;
@@ -1615,12 +1615,12 @@
         return;
     }
 
-    android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
+    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)image;
     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
-    if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
+    if (native_buffer->common.version != sizeof(ANativeWindowBuffer)) {
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
@@ -1643,12 +1643,12 @@
         return;
     }
 
-    android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
+    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)image;
     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
-    if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
+    if (native_buffer->common.version != sizeof(ANativeWindowBuffer)) {
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
diff --git a/opengl/libagl2/Android.mk b/opengl/libagl2/Android.mk
new file mode 100644
index 0000000..564932f
--- /dev/null
+++ b/opengl/libagl2/Android.mk
@@ -0,0 +1,58 @@
+LOCAL_PATH:= $(call my-dir)
+
+#
+# Build the software OpenGL ES library
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	src/api.cpp \
+	src/egl.cpp \
+    src/get.cpp \
+	src/shader.cpp \
+	src/state.cpp \
+	src/texture.cpp \
+	src/vertex.cpp
+
+LOCAL_C_INCLUDES :=	\
+    $(LOCAL_PATH) \
+    external/mesa3d/include \
+    external/mesa3d/src \
+    external/stlport/stlport \
+    bionic
+    
+#LOCAL_CFLAGS += -DLOG_TAG=\"libagl2\"
+#LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+#LOCAL_CFLAGS += -fvisibility=hidden
+#LOCAL_CFLAGS += -O0 -g -DDEBUG -UNDEBUG
+LOCAL_CFLAGS += -O3
+LOCAL_STATIC_LIBRARIES := libMesa
+LOCAL_SHARED_LIBRARIES := libstlport libcutils libhardware libutils libbcc libdl
+LOCAL_LDLIBS := -lpthread
+
+ifeq ($(TARGET_ARCH),arm)
+	LOCAL_CFLAGS += -fstrict-aliasing
+endif
+
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+    # we need to access the private Bionic header <bionic_tls.h>
+    # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+    # behavior from the bionic Android.mk file
+    ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+    endif
+    LOCAL_C_INCLUDES += bionic/libc/private
+endif
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
+#replace libagl for now
+LOCAL_MODULE:= libGLES_android
+LOCAL_MODULE_TAGS := eng
+
+## Disable this makefile for now
+## include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libagl2/README b/opengl/libagl2/README
new file mode 100644
index 0000000..34746d3
--- /dev/null
+++ b/opengl/libagl2/README
@@ -0,0 +1,26 @@
+libAgl2 provides software GL ES 2.0 implementation using Pixelflinger2 in external/mesa3d
+
+To build, enable Android.mk, which builds libGLES_android.so, then replace the one built from libAgl in system/lib/egl.
+ES 1.0 functions are not implemented and will cause exit, so do not setprop debug.egl.hw 0 until launcher is loaded.
+
+All functions have little to none error checking.
+Not thread safe, Pixelflinger2 uses some static data.
+
+Most shader functions are implemented, however, most Get* functions for shaders/programs/uniforms/attribs are not.
+No name system for shaders/programs, just using the pointers as names.
+
+Basic glTexImage2D, glTexSubImage2D, glCopyImage2D and glCopySubImage2D are implemented, with a range of 8/16/24/32bpp formats.
+Cube map support is minimal. No mipmapping.
+TexParameter is mostly implemented, supports texcoord wrap modes, and only linear for both min and mag, or nearest for both min and mag filtering.
+Texture names are implemented, but bad.
+
+Frame buffer and render buffers are not implemented.
+
+Depth and stencil are implemented, but not tested.
+Blending seems to work.
+Colorbuffer supports RGBA_8888 and RGB_565.
+
+Vertex buffer objects are implemented.
+Some GL_TRIANGLES and GL_TRIANGLE_STRIPS modes for glDrawArrays and glDrawElements are implemented, but vertex order is probably wrong so culling is disabled.
+
+Basic apps should work, and some libhwui should work, except for frame buffer operations, which will cause exit.
diff --git a/opengl/libagl2/libagl2.project b/opengl/libagl2/libagl2.project
new file mode 100644
index 0000000..f234421
--- /dev/null
+++ b/opengl/libagl2/libagl2.project
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<CodeLite_Project Name="libagl2" InternalType="Console">
+  <Plugins>
+    <Plugin Name="qmake">
+      <![CDATA[00010001N0005Debug000000000000]]>
+    </Plugin>
+  </Plugins>
+  <Description/>
+  <Dependencies/>
+  <Dependencies Name="Release"/>
+  <VirtualDirectory Name="src">
+    <File Name="src/egl.cpp"/>
+    <File Name="src/api.cpp"/>
+    <File Name="src/gles2context.h"/>
+    <File Name="src/shader.cpp"/>
+    <File Name="src/vertex.cpp"/>
+    <File Name="src/state.cpp"/>
+    <File Name="src/texture.cpp"/>
+    <File Name="src/get.cpp"/>
+  </VirtualDirectory>
+  <VirtualDirectory Name="include"/>
+  <Settings Type="Executable">
+    <Configuration Name="Debug" CompilerType="gnu gcc" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
+      <Compiler Options="-g;-m32" Required="yes" PreCompiledHeader="">
+        <IncludePath Value="/usr/include/c++/4.4"/>
+        <IncludePath Value="/usr/include/c++/4.4/ext"/>
+        <IncludePath Value="."/>
+        <IncludePath Value="include"/>
+        <IncludePath Value="../../../../external/mesa3d/include"/>
+        <IncludePath Value="../../../../external/mesa3d/src"/>
+        <IncludePath Value="../../../../hardware/libhardware/include"/>
+        <IncludePath Value="../../../../system/core/include"/>
+        <IncludePath Value="../include"/>
+        <IncludePath Value="../../include"/>
+        <IncludePath Value="../../../../development/ndk/platforms/android-9/include"/>
+        <IncludePath Value="../../../../bionic/libc/include/"/>
+        <IncludePath Value="/../../../../development/ndk/platforms/android-5/arch-x86/include"/>
+        <IncludePath Value="../../../../bionic/libc/arch-x86/include"/>
+        <IncludePath Value="../../../../bionic/libc/kernel/arch-x86"/>
+        <IncludePath Value="/../../../../external/kernel-headers/original"/>
+        <IncludePath Value="../../../../prebuilt/ndk/android-ndk-r4/platforms/android-8/arch-x86/usr/include"/>
+      </Compiler>
+      <Linker Options="-m32;-lstdc++" Required="yes"/>
+      <ResourceCompiler Options="" Required="no"/>
+      <General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Debug" Command="./$(ProjectName)" CommandArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
+      <Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
+        <PostConnectCommands/>
+        <StartupCommands/>
+      </Debugger>
+      <PreBuild/>
+      <PostBuild/>
+      <CustomBuild Enabled="no">
+        <RebuildCommand/>
+        <CleanCommand/>
+        <BuildCommand/>
+        <PreprocessFileCommand/>
+        <SingleFileCommand/>
+        <MakefileGenerationCommand/>
+        <ThirdPartyToolName>None</ThirdPartyToolName>
+        <WorkingDirectory/>
+      </CustomBuild>
+      <AdditionalRules>
+        <CustomPostBuild/>
+        <CustomPreBuild/>
+      </AdditionalRules>
+    </Configuration>
+    <Configuration Name="Release" CompilerType="gnu gcc" DebuggerType="GNU gdb debugger" Type="" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
+      <Compiler Options="" Required="yes" PreCompiledHeader="">
+        <IncludePath Value="."/>
+      </Compiler>
+      <Linker Options="-O2" Required="yes"/>
+      <ResourceCompiler Options="" Required="no"/>
+      <General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Release" Command="./$(ProjectName)" CommandArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
+      <Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
+        <PostConnectCommands/>
+        <StartupCommands/>
+      </Debugger>
+      <PreBuild/>
+      <PostBuild/>
+      <CustomBuild Enabled="no">
+        <RebuildCommand/>
+        <CleanCommand/>
+        <BuildCommand/>
+        <PreprocessFileCommand/>
+        <SingleFileCommand/>
+        <MakefileGenerationCommand/>
+        <ThirdPartyToolName>None</ThirdPartyToolName>
+        <WorkingDirectory/>
+      </CustomBuild>
+      <AdditionalRules>
+        <CustomPostBuild/>
+        <CustomPreBuild/>
+      </AdditionalRules>
+    </Configuration>
+    <GlobalSettings>
+      <Compiler Options="">
+        <IncludePath Value="."/>
+      </Compiler>
+      <Linker Options="">
+        <LibraryPath Value="."/>
+      </Linker>
+      <ResourceCompiler Options=""/>
+    </GlobalSettings>
+  </Settings>
+  <Dependencies Name="Debug">
+    <Project Name="libMesa"/>
+  </Dependencies>
+</CodeLite_Project>
diff --git a/opengl/libagl2/src/api.cpp b/opengl/libagl2/src/api.cpp
new file mode 100644
index 0000000..bb8d62b
--- /dev/null
+++ b/opengl/libagl2/src/api.cpp
@@ -0,0 +1,266 @@
+#include "gles2context.h"
+
+#define API_ENTRY
+#define CALL_GL_API(NAME,...) LOGD("?"#NAME); assert(0);
+#define CALL_GL_API_RETURN(NAME,...) LOGD("?"#NAME); assert(0); return 0;
+
+
+void API_ENTRY(glBindFramebuffer)(GLenum target, GLuint framebuffer)
+{
+   CALL_GL_API(glBindFramebuffer, target, framebuffer);
+}
+void API_ENTRY(glBindRenderbuffer)(GLenum target, GLuint renderbuffer)
+{
+   CALL_GL_API(glBindRenderbuffer, target, renderbuffer);
+}
+GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target)
+{
+   CALL_GL_API_RETURN(glCheckFramebufferStatus, target);
+}
+void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+   CALL_GL_API(glColorMask, red, green, blue, alpha);
+}
+void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers)
+{
+   CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers)
+{
+   CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glDepthFunc)(GLenum func)
+{
+   CALL_GL_API(glDepthFunc, func);
+}
+void API_ENTRY(glDepthMask)(GLboolean flag)
+{
+   CALL_GL_API(glDepthMask, flag);
+}
+void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar)
+{
+   CALL_GL_API(glDepthRangef, zNear, zFar);
+}
+void API_ENTRY(glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+   CALL_GL_API(glFramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer);
+}
+void API_ENTRY(glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+   CALL_GL_API(glFramebufferTexture2D, target, attachment, textarget, texture, level);
+}
+void glGenerateMipmap(GLenum target)
+{
+   //CALL_GL_API(glGenerateMipmap, target);
+   LOGD("agl2: glGenerateMipmap not implemented");
+}
+void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint* framebuffers)
+{
+   CALL_GL_API(glGenFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers)
+{
+   CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+   CALL_GL_API(glGetActiveAttrib, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+   CALL_GL_API(glGetActiveUniform, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+   CALL_GL_API(glGetAttachedShaders, program, maxcount, count, shaders);
+}
+void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean* params)
+{
+   CALL_GL_API(glGetBooleanv, pname, params);
+}
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+}
+GLenum glGetError(void)
+{
+   puts("agl2: glGetError");
+   return GL_NO_ERROR;
+   //CALL_GL_API_RETURN(glGetError);
+}
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat* params)
+{
+   CALL_GL_API(glGetFloatv, pname, params);
+}
+void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
+}
+void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+   CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
+}
+void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+   CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
+}
+void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat* params)
+{
+   CALL_GL_API(glGetUniformfv, program, location, params);
+}
+void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint* params)
+{
+   CALL_GL_API(glGetUniformiv, program, location, params);
+}
+void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params)
+{
+   CALL_GL_API(glGetVertexAttribfv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetVertexAttribiv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer)
+{
+   CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
+}
+GLboolean API_ENTRY(glIsBuffer)(GLuint buffer)
+{
+   CALL_GL_API_RETURN(glIsBuffer, buffer);
+}
+GLboolean API_ENTRY(glIsEnabled)(GLenum cap)
+{
+   CALL_GL_API_RETURN(glIsEnabled, cap);
+}
+GLboolean API_ENTRY(glIsFramebuffer)(GLuint framebuffer)
+{
+   CALL_GL_API_RETURN(glIsFramebuffer, framebuffer);
+}
+GLboolean API_ENTRY(glIsProgram)(GLuint program)
+{
+   CALL_GL_API_RETURN(glIsProgram, program);
+}
+GLboolean API_ENTRY(glIsRenderbuffer)(GLuint renderbuffer)
+{
+   CALL_GL_API_RETURN(glIsRenderbuffer, renderbuffer);
+}
+GLboolean API_ENTRY(glIsShader)(GLuint shader)
+{
+   CALL_GL_API_RETURN(glIsShader, shader);
+}
+void API_ENTRY(glLineWidth)(GLfloat width)
+{
+   CALL_GL_API(glLineWidth, width);
+}
+void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units)
+{
+   CALL_GL_API(glPolygonOffset, factor, units);
+}
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+{
+   CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
+}
+void API_ENTRY(glReleaseShaderCompiler)(void)
+{
+   CALL_GL_API(glReleaseShaderCompiler);
+}
+void API_ENTRY(glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+   CALL_GL_API(glRenderbufferStorage, target, internalformat, width, height);
+}
+void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert)
+{
+   CALL_GL_API(glSampleCoverage, value, invert);
+}
+void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+{
+   CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length);
+}
+void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask)
+{
+   CALL_GL_API(glStencilFunc, func, ref, mask);
+}
+void API_ENTRY(glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+   CALL_GL_API(glStencilFuncSeparate, face, func, ref, mask);
+}
+void API_ENTRY(glStencilMask)(GLuint mask)
+{
+   CALL_GL_API(glStencilMask, mask);
+}
+void API_ENTRY(glStencilMaskSeparate)(GLenum face, GLuint mask)
+{
+   CALL_GL_API(glStencilMaskSeparate, face, mask);
+}
+void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass)
+{
+   CALL_GL_API(glStencilOp, fail, zfail, zpass);
+}
+void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+   CALL_GL_API(glStencilOpSeparate, face, fail, zfail, zpass);
+}
+void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat* v)
+{
+   CALL_GL_API(glUniform1fv, location, count, v);
+}
+void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint* v)
+{
+   CALL_GL_API(glUniform1iv, location, count, v);
+}
+void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat* v)
+{
+   CALL_GL_API(glUniform2fv, location, count, v);
+}
+void API_ENTRY(glUniform2i)(GLint location, GLint x, GLint y)
+{
+   CALL_GL_API(glUniform2i, location, x, y);
+}
+void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint* v)
+{
+   CALL_GL_API(glUniform2iv, location, count, v);
+}
+void API_ENTRY(glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+   CALL_GL_API(glUniform3f, location, x, y, z);
+}
+void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat* v)
+{
+   CALL_GL_API(glUniform3fv, location, count, v);
+}
+void API_ENTRY(glUniform3i)(GLint location, GLint x, GLint y, GLint z)
+{
+   CALL_GL_API(glUniform3i, location, x, y, z);
+}
+void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint* v)
+{
+   CALL_GL_API(glUniform3iv, location, count, v);
+}
+void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat* v)
+{
+   CALL_GL_API(glUniform4fv, location, count, v);
+}
+void API_ENTRY(glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+   CALL_GL_API(glUniform4i, location, x, y, z, w);
+}
+void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint* v)
+{
+   CALL_GL_API(glUniform4iv, location, count, v);
+}
+void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+   CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+   CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value);
+}
+void API_ENTRY(glValidateProgram)(GLuint program)
+{
+   CALL_GL_API(glValidateProgram, program);
+}
diff --git a/opengl/libagl2/src/egl.cpp b/opengl/libagl2/src/egl.cpp
new file mode 100644
index 0000000..0d02ce6
--- /dev/null
+++ b/opengl/libagl2/src/egl.cpp
@@ -0,0 +1,2172 @@
+/*
+ **
+ ** Copyright 2007 The Android Open Source Project
+ **
+ ** Licensed under the Apache License Version 2.0(the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing software
+ ** distributed under the License is distributed on an "AS IS" BASIS
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <cutils/atomic.h>
+
+
+#include <private/ui/android_natives_priv.h>
+
+#include "gles2context.h"
+
+// ----------------------------------------------------------------------------
+namespace android
+{
+// ----------------------------------------------------------------------------
+
+const unsigned int NUM_DISPLAYS = 1;
+
+static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_key_t gEGLErrorKey = -1;
+#ifndef HAVE_ANDROID_OS
+namespace gl {
+pthread_key_t gGLKey = -1;
+}; // namespace gl
+#endif
+
+template<typename T>
+static T setError(GLint error, T returnValue)
+{
+    if (ggl_unlikely(gEGLErrorKey == -1)) {
+        pthread_mutex_lock(&gErrorKeyMutex);
+        if (gEGLErrorKey == -1)
+            pthread_key_create(&gEGLErrorKey, NULL);
+        pthread_mutex_unlock(&gErrorKeyMutex);
+    }
+    pthread_setspecific(gEGLErrorKey, (void*)error);
+    return returnValue;
+}
+
+static GLint getError()
+{
+    if (ggl_unlikely(gEGLErrorKey == -1))
+        return EGL_SUCCESS;
+    GLint error = (GLint)pthread_getspecific(gEGLErrorKey);
+    if (error == 0) {
+        // The TLS key has been created by another thread, but the value for
+        // this thread has not been initialized.
+        return EGL_SUCCESS;
+    }
+    pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS);
+    return error;
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_display_t {
+    egl_display_t() : type(0), initialized(0) { }
+
+    static egl_display_t& get_display(EGLDisplay dpy);
+
+    static EGLBoolean is_valid(EGLDisplay dpy) {
+        return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
+    }
+
+    NativeDisplayType   type;
+    volatile int32_t    initialized;
+};
+
+static egl_display_t gDisplays[NUM_DISPLAYS];
+
+egl_display_t& egl_display_t::get_display(EGLDisplay dpy)
+{
+    return gDisplays[uintptr_t(dpy)-1U];
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_surface_t {
+    enum {
+        PAGE_FLIP = 0x00000001,
+        MAGIC     = 0x31415265
+    };
+
+    uint32_t            magic;
+    EGLDisplay          dpy;
+    EGLConfig           config;
+    EGLContext          ctx;
+
+    egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
+    virtual     ~egl_surface_t();
+    bool    isValid() const;
+    virtual     bool    initCheck() const = 0;
+
+    virtual     EGLBoolean  bindDrawSurface(GLES2Context* gl) = 0;
+    virtual     EGLBoolean  bindReadSurface(GLES2Context* gl) = 0;
+    virtual     EGLBoolean  connect() {
+        return EGL_TRUE;
+    }
+    virtual     void        disconnect() {}
+    virtual     EGLint      getWidth() const = 0;
+    virtual     EGLint      getHeight() const = 0;
+
+    virtual     EGLint      getHorizontalResolution() const;
+    virtual     EGLint      getVerticalResolution() const;
+    virtual     EGLint      getRefreshRate() const;
+    virtual     EGLint      getSwapBehavior() const;
+    virtual     EGLBoolean  swapBuffers();
+    virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+protected:
+    GGLSurface              depth;
+};
+
+egl_surface_t::egl_surface_t(EGLDisplay dpy,
+        EGLConfig config,
+        int32_t depthFormat)
+: magic(MAGIC), dpy(dpy), config(config), ctx(0)
+{
+    depth.version = sizeof(GGLSurface);
+    depth.data = 0;
+    depth.format = (GGLPixelFormat)depthFormat;
+}
+egl_surface_t::~egl_surface_t()
+{
+    magic = 0;
+    free(depth.data);
+}
+bool egl_surface_t::isValid() const
+{
+    LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
+    return magic == MAGIC;
+}
+
+EGLBoolean egl_surface_t::swapBuffers()
+{
+    return EGL_FALSE;
+}
+EGLint egl_surface_t::getHorizontalResolution() const
+{
+    return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+}
+EGLint egl_surface_t::getVerticalResolution() const
+{
+    return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+}
+EGLint egl_surface_t::getRefreshRate() const
+{
+    return (60 * EGL_DISPLAY_SCALING);
+}
+EGLint egl_surface_t::getSwapBehavior() const
+{
+    return EGL_BUFFER_PRESERVED;
+}
+EGLBoolean egl_surface_t::setSwapRectangle(
+        EGLint l, EGLint t, EGLint w, EGLint h)
+{
+    return EGL_FALSE;
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_window_surface_v2_t : public egl_surface_t {
+    egl_window_surface_v2_t(
+            EGLDisplay dpy, EGLConfig config,
+            int32_t depthFormat,
+            ANativeWindow* window);
+
+    ~egl_window_surface_v2_t();
+
+    virtual     bool        initCheck() const {
+        return true;   // TODO: report failure if ctor fails
+    }
+    virtual     EGLBoolean  swapBuffers();
+    virtual     EGLBoolean  bindDrawSurface(GLES2Context* gl);
+    virtual     EGLBoolean  bindReadSurface(GLES2Context* gl);
+    virtual     EGLBoolean  connect();
+    virtual     void        disconnect();
+    virtual     EGLint      getWidth() const    {
+        return width;
+    }
+    virtual     EGLint      getHeight() const   {
+        return height;
+    }
+    virtual     EGLint      getHorizontalResolution() const;
+    virtual     EGLint      getVerticalResolution() const;
+    virtual     EGLint      getRefreshRate() const;
+    virtual     EGLint      getSwapBehavior() const;
+    virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+
+private:
+    status_t lock(ANativeWindowBuffer* buf, int usage, void** vaddr);
+    status_t unlock(ANativeWindowBuffer* buf);
+    ANativeWindow*   nativeWindow;
+    ANativeWindowBuffer*   buffer;
+    ANativeWindowBuffer*   previousBuffer;
+    gralloc_module_t const*    module;
+    int width;
+    int height;
+    void* bits;
+    GGLFormat const* pixelFormatTable;
+
+    struct Rect {
+        inline Rect() { };
+        inline Rect(int32_t w, int32_t h)
+        : left(0), top(0), right(w), bottom(h) { }
+        inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
+        : left(l), top(t), right(r), bottom(b) { }
+        Rect& andSelf(const Rect& r) {
+            left   = max(left, r.left);
+            top    = max(top, r.top);
+            right  = min(right, r.right);
+            bottom = min(bottom, r.bottom);
+            return *this;
+        }
+        bool isEmpty() const {
+            return (left>=right || top>=bottom);
+        }
+        void dump(char const* what) {
+            LOGD("%s { %5d, %5d, w=%5d, h=%5d }",
+                    what, left, top, right-left, bottom-top);
+        }
+
+        int32_t left;
+        int32_t top;
+        int32_t right;
+        int32_t bottom;
+    };
+
+    struct Region {
+        inline Region() : count(0) { }
+        typedef Rect const* const_iterator;
+        const_iterator begin() const {
+            return storage;
+        }
+        const_iterator end() const {
+            return storage+count;
+        }
+        static Region subtract(const Rect& lhs, const Rect& rhs) {
+            Region reg;
+            Rect* storage = reg.storage;
+            if (!lhs.isEmpty()) {
+                if (lhs.top < rhs.top) { // top rect
+                    storage->left   = lhs.left;
+                    storage->top    = lhs.top;
+                    storage->right  = lhs.right;
+                    storage->bottom = rhs.top;
+                    storage++;
+                }
+                const int32_t top = max(lhs.top, rhs.top);
+                const int32_t bot = min(lhs.bottom, rhs.bottom);
+                if (top < bot) {
+                    if (lhs.left < rhs.left) { // left-side rect
+                        storage->left   = lhs.left;
+                        storage->top    = top;
+                        storage->right  = rhs.left;
+                        storage->bottom = bot;
+                        storage++;
+                    }
+                    if (lhs.right > rhs.right) { // right-side rect
+                        storage->left   = rhs.right;
+                        storage->top    = top;
+                        storage->right  = lhs.right;
+                        storage->bottom = bot;
+                        storage++;
+                    }
+                }
+                if (lhs.bottom > rhs.bottom) { // bottom rect
+                    storage->left   = lhs.left;
+                    storage->top    = rhs.bottom;
+                    storage->right  = lhs.right;
+                    storage->bottom = lhs.bottom;
+                    storage++;
+                }
+                reg.count = storage - reg.storage;
+            }
+            return reg;
+        }
+        bool isEmpty() const {
+            return count<=0;
+        }
+    private:
+        Rect storage[4];
+        ssize_t count;
+    };
+
+    void copyBlt(
+            ANativeWindowBuffer* dst, void* dst_vaddr,
+            ANativeWindowBuffer* src, void const* src_vaddr,
+            const Region& clip);
+
+    Rect dirtyRegion;
+    Rect oldDirtyRegion;
+};
+
+egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
+        EGLConfig config,
+        int32_t depthFormat,
+        ANativeWindow* window)
+: egl_surface_t(dpy, config, depthFormat),
+  nativeWindow(window), buffer(0), previousBuffer(0), module(0),
+  bits(NULL)
+{
+    pixelFormatTable = gglGetPixelFormatTable();
+
+    // keep a reference on the window
+    nativeWindow->common.incRef(&nativeWindow->common);
+    nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
+    nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
+    int format = 0;
+    nativeWindow->query(nativeWindow, NATIVE_WINDOW_FORMAT, &format);
+    LOGD("agl2: egl_window_surface_v2_t format=0x%.4X", format);
+    //   assert(0);
+}
+
+egl_window_surface_v2_t::~egl_window_surface_v2_t()
+{
+    if (buffer) {
+        buffer->common.decRef(&buffer->common);
+    }
+    if (previousBuffer) {
+        previousBuffer->common.decRef(&previousBuffer->common);
+    }
+    nativeWindow->common.decRef(&nativeWindow->common);
+}
+
+EGLBoolean egl_window_surface_v2_t::connect()
+{
+    // we're intending to do software rendering
+    native_window_set_usage(nativeWindow,
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
+    // dequeue a buffer
+    if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
+        return setError(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    // allocate a corresponding depth-buffer
+    width = buffer->width;
+    height = buffer->height;
+    if (depth.format) {
+        depth.width   = width;
+        depth.height  = height;
+        depth.stride  = depth.width; // use the width here
+        assert(GGL_PIXEL_FORMAT_Z_32 == depth.format);
+        depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*4);
+        if (depth.data == 0) {
+            return setError(EGL_BAD_ALLOC, EGL_FALSE);
+        }
+    }
+
+    // keep a reference on the buffer
+    buffer->common.incRef(&buffer->common);
+
+    // Lock the buffer
+    nativeWindow->lockBuffer(nativeWindow, buffer);
+    // pin the buffer down
+    if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+            GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+        LOGE("connect() failed to lock buffer %p (%ux%u)",
+                buffer, buffer->width, buffer->height);
+        return setError(EGL_BAD_ACCESS, EGL_FALSE);
+        // FIXME: we should make sure we're not accessing the buffer anymore
+    }
+    return EGL_TRUE;
+}
+
+void egl_window_surface_v2_t::disconnect()
+{
+    if (buffer && bits) {
+        bits = NULL;
+        unlock(buffer);
+    }
+    // enqueue the last frame
+    if (buffer)
+        nativeWindow->queueBuffer(nativeWindow, buffer);
+    if (buffer) {
+        buffer->common.decRef(&buffer->common);
+        buffer = 0;
+    }
+    if (previousBuffer) {
+        previousBuffer->common.decRef(&previousBuffer->common);
+        previousBuffer = 0;
+    }
+}
+
+status_t egl_window_surface_v2_t::lock(
+        ANativeWindowBuffer* buf, int usage, void** vaddr)
+{
+    int err;
+
+    err = module->lock(module, buf->handle,
+            usage, 0, 0, buf->width, buf->height, vaddr);
+
+    return err;
+}
+
+status_t egl_window_surface_v2_t::unlock(ANativeWindowBuffer* buf)
+{
+    if (!buf) return BAD_VALUE;
+    int err = NO_ERROR;
+
+    err = module->unlock(module, buf->handle);
+
+    return err;
+}
+
+void egl_window_surface_v2_t::copyBlt(
+        ANativeWindowBuffer* dst, void* dst_vaddr,
+        ANativeWindowBuffer* src, void const* src_vaddr,
+        const Region& clip)
+{
+    // NOTE: dst and src must be the same format
+
+    Region::const_iterator cur = clip.begin();
+    Region::const_iterator end = clip.end();
+
+    const size_t bpp = pixelFormatTable[src->format].size;
+    const size_t dbpr = dst->stride * bpp;
+    const size_t sbpr = src->stride * bpp;
+
+    uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
+    uint8_t       * const dst_bits = (uint8_t       *)dst_vaddr;
+
+    while (cur != end) {
+        const Rect& r(*cur++);
+        ssize_t w = r.right - r.left;
+        ssize_t h = r.bottom - r.top;
+        if (w <= 0 || h<=0) continue;
+        size_t size = w * bpp;
+        uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+        uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
+        if (dbpr==sbpr && size==sbpr) {
+            size *= h;
+            h = 1;
+        }
+        do {
+            memcpy(d, s, size);
+            d += dbpr;
+            s += sbpr;
+        } while (--h > 0);
+    }
+}
+
+EGLBoolean egl_window_surface_v2_t::swapBuffers()
+{
+    if (!buffer) {
+        return setError(EGL_BAD_ACCESS, EGL_FALSE);
+    }
+
+    /*
+     * Handle eglSetSwapRectangleANDROID()
+     * We copyback from the front buffer
+     */
+    if (!dirtyRegion.isEmpty()) {
+        dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
+        if (previousBuffer) {
+            // This was const Region copyBack, but that causes an
+            // internal compile error on simulator builds
+            /*const*/
+            Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
+            if (!copyBack.isEmpty()) {
+                void* prevBits;
+                if (lock(previousBuffer,
+                        GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
+                    // copy from previousBuffer to buffer
+                    copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
+                    unlock(previousBuffer);
+                }
+            }
+        }
+        oldDirtyRegion = dirtyRegion;
+    }
+
+    if (previousBuffer) {
+        previousBuffer->common.decRef(&previousBuffer->common);
+        previousBuffer = 0;
+    }
+
+    unlock(buffer);
+    previousBuffer = buffer;
+    nativeWindow->queueBuffer(nativeWindow, buffer);
+    buffer = 0;
+
+    // dequeue a new buffer
+    if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) {
+
+        // TODO: lockBuffer should rather be executed when the very first
+        // direct rendering occurs.
+        nativeWindow->lockBuffer(nativeWindow, buffer);
+
+        // reallocate the depth-buffer if needed
+        if ((width != buffer->width) || (height != buffer->height)) {
+            // TODO: we probably should reset the swap rect here
+            // if the window size has changed
+            width = buffer->width;
+            height = buffer->height;
+            if (depth.data) {
+                free(depth.data);
+                depth.width   = width;
+                depth.height  = height;
+                depth.stride  = buffer->stride;
+                depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
+                if (depth.data == 0) {
+                    setError(EGL_BAD_ALLOC, EGL_FALSE);
+                    return EGL_FALSE;
+                }
+            }
+        }
+
+        // keep a reference on the buffer
+        buffer->common.incRef(&buffer->common);
+
+        // finally pin the buffer down
+        if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+                GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+            LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
+                    buffer, buffer->width, buffer->height);
+            return setError(EGL_BAD_ACCESS, EGL_FALSE);
+            // FIXME: we should make sure we're not accessing the buffer anymore
+        }
+    } else {
+        return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
+    }
+
+    return EGL_TRUE;
+}
+
+EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
+        EGLint l, EGLint t, EGLint w, EGLint h)
+{
+    dirtyRegion = Rect(l, t, l+w, t+h);
+    return EGL_TRUE;
+}
+
+EGLBoolean egl_window_surface_v2_t::bindDrawSurface(GLES2Context* gl)
+{
+    GGLSurface buffer;
+    buffer.version = sizeof(GGLSurface);
+    buffer.width   = this->buffer->width;
+    buffer.height  = this->buffer->height;
+    buffer.stride  = this->buffer->stride;
+    buffer.data    = (GGLubyte*)bits;
+    buffer.format  = (GGLPixelFormat)this->buffer->format;
+    gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
+    if (depth.data != gl->rasterizer.depthSurface.data)
+        gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+
+    return EGL_TRUE;
+}
+EGLBoolean egl_window_surface_v2_t::bindReadSurface(GLES2Context* gl)
+{
+    GGLSurface buffer;
+    buffer.version = sizeof(GGLSurface);
+    buffer.width   = this->buffer->width;
+    buffer.height  = this->buffer->height;
+    buffer.stride  = this->buffer->stride;
+    buffer.data    = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
+    buffer.format  = (GGLPixelFormat)this->buffer->format;
+    puts("agl2: readBuffer not implemented");
+    //gl->rasterizer.interface.readBuffer(gl, &buffer);
+    return EGL_TRUE;
+}
+EGLint egl_window_surface_v2_t::getHorizontalResolution() const
+{
+    return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+}
+EGLint egl_window_surface_v2_t::getVerticalResolution() const
+{
+    return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+}
+EGLint egl_window_surface_v2_t::getRefreshRate() const
+{
+    return (60 * EGL_DISPLAY_SCALING); // FIXME
+}
+EGLint egl_window_surface_v2_t::getSwapBehavior() const
+{
+    /*
+     * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
+     * the content of the swapped buffer.
+     *
+     * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
+     *
+     * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
+     * only applies to the area specified by eglSetSwapRectangleANDROID(), that
+     * is, everything outside of this area is preserved.
+     *
+     * This implementation of EGL assumes the later case.
+     *
+     */
+
+    return EGL_BUFFER_DESTROYED;
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_pixmap_surface_t : public egl_surface_t {
+    egl_pixmap_surface_t(
+            EGLDisplay dpy, EGLConfig config,
+            int32_t depthFormat,
+            egl_native_pixmap_t const * pixmap);
+
+    virtual ~egl_pixmap_surface_t() { }
+
+    virtual     bool        initCheck() const {
+        return !depth.format || depth.data!=0;
+    }
+    virtual     EGLBoolean  bindDrawSurface(GLES2Context* gl);
+    virtual     EGLBoolean  bindReadSurface(GLES2Context* gl);
+    virtual     EGLint      getWidth() const    {
+        return nativePixmap.width;
+    }
+    virtual     EGLint      getHeight() const   {
+        return nativePixmap.height;
+    }
+private:
+    egl_native_pixmap_t     nativePixmap;
+};
+
+egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
+        EGLConfig config,
+        int32_t depthFormat,
+        egl_native_pixmap_t const * pixmap)
+: egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
+{
+    if (depthFormat) {
+        depth.width   = pixmap->width;
+        depth.height  = pixmap->height;
+        depth.stride  = depth.width; // use the width here
+        depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
+        if (depth.data == 0) {
+            setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+        }
+    }
+}
+EGLBoolean egl_pixmap_surface_t::bindDrawSurface(GLES2Context* gl)
+{
+    GGLSurface buffer;
+    buffer.version = sizeof(GGLSurface);
+    buffer.width   = nativePixmap.width;
+    buffer.height  = nativePixmap.height;
+    buffer.stride  = nativePixmap.stride;
+    buffer.data    = nativePixmap.data;
+    buffer.format  = (GGLPixelFormat)nativePixmap.format;
+
+    gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
+    if (depth.data != gl->rasterizer.depthSurface.data)
+        gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+    return EGL_TRUE;
+}
+EGLBoolean egl_pixmap_surface_t::bindReadSurface(GLES2Context* gl)
+{
+    GGLSurface buffer;
+    buffer.version = sizeof(GGLSurface);
+    buffer.width   = nativePixmap.width;
+    buffer.height  = nativePixmap.height;
+    buffer.stride  = nativePixmap.stride;
+    buffer.data    = nativePixmap.data;
+    buffer.format  = (GGLPixelFormat)nativePixmap.format;
+    puts("agl2: readBuffer not implemented");
+    //gl->rasterizer.interface.readBuffer(gl, &buffer);
+    return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_pbuffer_surface_t : public egl_surface_t {
+    egl_pbuffer_surface_t(
+            EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
+            int32_t w, int32_t h, int32_t f);
+
+    virtual ~egl_pbuffer_surface_t();
+
+    virtual     bool        initCheck() const   {
+        return pbuffer.data != 0;
+    }
+    virtual     EGLBoolean  bindDrawSurface(GLES2Context* gl);
+    virtual     EGLBoolean  bindReadSurface(GLES2Context* gl);
+    virtual     EGLint      getWidth() const    {
+        return pbuffer.width;
+    }
+    virtual     EGLint      getHeight() const   {
+        return pbuffer.height;
+    }
+private:
+    GGLSurface  pbuffer;
+};
+
+egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
+        EGLConfig config, int32_t depthFormat,
+        int32_t w, int32_t h, int32_t f)
+: egl_surface_t(dpy, config, depthFormat)
+{
+    size_t size = w*h;
+    switch (f) {
+        case GGL_PIXEL_FORMAT_A_8:
+            size *= 1;
+            break;
+        case GGL_PIXEL_FORMAT_RGB_565:
+            size *= 2;
+            break;
+        case GGL_PIXEL_FORMAT_RGBA_8888:
+            size *= 4;
+            break;
+        case GGL_PIXEL_FORMAT_RGBX_8888:
+            size *= 4;
+            break;
+        default:
+            LOGE("incompatible pixel format for pbuffer (format=%d)", f);
+            pbuffer.data = 0;
+            break;
+    }
+    pbuffer.version = sizeof(GGLSurface);
+    pbuffer.width   = w;
+    pbuffer.height  = h;
+    pbuffer.stride  = w;
+    pbuffer.data    = (GGLubyte*)malloc(size);
+    pbuffer.format  = (GGLPixelFormat)f;
+
+    if (depthFormat) {
+        depth.width   = pbuffer.width;
+        depth.height  = pbuffer.height;
+        depth.stride  = depth.width; // use the width here
+        depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
+        if (depth.data == 0) {
+            setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+            return;
+        }
+    }
+}
+egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
+{
+    free(pbuffer.data);
+}
+EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(GLES2Context* gl)
+{
+    gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &pbuffer);
+    if (depth.data != gl->rasterizer.depthSurface.data)
+        gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+    return EGL_TRUE;
+}
+EGLBoolean egl_pbuffer_surface_t::bindReadSurface(GLES2Context* gl)
+{
+    puts("agl2: readBuffer not implemented");
+    //gl->rasterizer.interface.readBuffer(gl, &pbuffer);
+    return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+
+struct config_pair_t {
+    GLint key;
+    GLint value;
+};
+
+struct configs_t {
+    const config_pair_t* array;
+    int                  size;
+};
+
+struct config_management_t {
+    GLint key;
+    bool (*match)(GLint reqValue, GLint confValue);
+    static bool atLeast(GLint reqValue, GLint confValue) {
+        return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
+    }
+    static bool exact(GLint reqValue, GLint confValue) {
+        return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
+    }
+    static bool mask(GLint reqValue, GLint confValue) {
+        return (confValue & reqValue) == reqValue;
+    }
+    static bool ignore(GLint reqValue, GLint confValue) {
+        return true;
+    }
+};
+
+// ----------------------------------------------------------------------------
+
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 2
+static char const * const gVendorString     = "Google Inc.";
+static char const * const gVersionString    = "0.0 Android Driver 0.0.0";
+static char const * const gClientApiString  = "OpenGL ES2";
+static char const * const gExtensionsString =
+        //"EGL_KHR_image_base "
+        // "KHR_image_pixmap "
+        //"EGL_ANDROID_image_native_buffer "
+        //"EGL_ANDROID_swap_rectangle "
+        "";
+
+// ----------------------------------------------------------------------------
+
+struct extention_map_t {
+    const char * const name;
+    __eglMustCastToProperFunctionPointerType address;
+};
+
+static const extention_map_t gExtentionMap[] = {
+        //    { "glDrawTexsOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
+        //    { "glDrawTexiOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
+        //    { "glDrawTexfOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
+        //    { "glDrawTexxOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
+        //    { "glDrawTexsvOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
+        //    { "glDrawTexivOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
+        //    { "glDrawTexfvOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
+        //    { "glDrawTexxvOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
+        //    { "glQueryMatrixxOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
+        //    { "glEGLImageTargetTexture2DOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
+        //    { "glEGLImageTargetRenderbufferStorageOES",
+        //            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
+        //    { "glClipPlanef",
+        //            (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
+        //    { "glClipPlanex",
+        //            (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
+        //    { "glBindBuffer",
+        //            (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
+        //    { "glBufferData",
+        //            (__eglMustCastToProperFunctionPointerType)&glBufferData },
+        //    { "glBufferSubData",
+        //            (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
+        //    { "glDeleteBuffers",
+        //            (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
+        //    { "glGenBuffers",
+        //            (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
+        //    { "eglCreateImageKHR",
+        //            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
+        //    { "eglDestroyImageKHR",
+        //            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
+        //    { "eglSetSwapRectangleANDROID",
+        //            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
+};
+
+/*
+ * In the lists below, attributes names MUST be sorted.
+ * Additionally, all configs must be sorted according to
+ * the EGL specification.
+ */
+
+static config_pair_t const config_base_attribute_list[] = {
+        { EGL_STENCIL_SIZE,               0                                 },
+        { EGL_CONFIG_CAVEAT,              EGL_SLOW_CONFIG                   },
+        { EGL_LEVEL,                      0                                 },
+        { EGL_MAX_PBUFFER_HEIGHT,         GGL_MAX_VIEWPORT_DIMS             },
+        { EGL_MAX_PBUFFER_PIXELS,
+                GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS                 },
+                { EGL_MAX_PBUFFER_WIDTH,          GGL_MAX_VIEWPORT_DIMS             },
+                { EGL_NATIVE_RENDERABLE,          EGL_TRUE                          },
+                { EGL_NATIVE_VISUAL_ID,           0                                 },
+                { EGL_NATIVE_VISUAL_TYPE,         GGL_PIXEL_FORMAT_RGBA_8888        },
+                { EGL_SAMPLES,                    0                                 },
+                { EGL_SAMPLE_BUFFERS,             0                                 },
+                { EGL_TRANSPARENT_TYPE,           EGL_NONE                          },
+                { EGL_TRANSPARENT_BLUE_VALUE,     0                                 },
+                { EGL_TRANSPARENT_GREEN_VALUE,    0                                 },
+                { EGL_TRANSPARENT_RED_VALUE,      0                                 },
+                { EGL_BIND_TO_TEXTURE_RGBA,       EGL_FALSE                         },
+                { EGL_BIND_TO_TEXTURE_RGB,        EGL_FALSE                         },
+                { EGL_MIN_SWAP_INTERVAL,          1                                 },
+                { EGL_MAX_SWAP_INTERVAL,          1                                 },
+                { EGL_LUMINANCE_SIZE,             0                                 },
+                { EGL_ALPHA_MASK_SIZE,            0                                 },
+                { EGL_COLOR_BUFFER_TYPE,          EGL_RGB_BUFFER                    },
+                { EGL_RENDERABLE_TYPE,            EGL_OPENGL_ES2_BIT                },
+                { EGL_CONFORMANT,                 0                                 }
+};
+
+// These configs can override the base attribute list
+// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
+
+// 565 configs
+static config_pair_t const config_0_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     16 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        5 },
+        { EGL_GREEN_SIZE,       6 },
+        { EGL_RED_SIZE,         5 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        0 },
+        { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
+        { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_1_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     16 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        5 },
+        { EGL_GREEN_SIZE,       6 },
+        { EGL_RED_SIZE,         5 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        1 },
+        { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
+        { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+// RGB 888 configs
+static config_pair_t const config_2_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        6 },
+        { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
+        { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_3_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        7 },
+        { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
+        { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+// 8888 configs
+static config_pair_t const config_4_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       8 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        2 },
+        { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
+        { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_5_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       8 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        3 },
+        { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
+        { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+// A8 configs
+static config_pair_t const config_6_attribute_list[] = {
+        { EGL_BUFFER_SIZE,      8 },
+        { EGL_ALPHA_SIZE,       8 },
+        { EGL_BLUE_SIZE,        0 },
+        { EGL_GREEN_SIZE,       0 },
+        { EGL_RED_SIZE,         0 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        4 },
+        { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
+        { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_7_attribute_list[] = {
+        { EGL_BUFFER_SIZE,      8 },
+        { EGL_ALPHA_SIZE,       8 },
+        { EGL_BLUE_SIZE,        0 },
+        { EGL_GREEN_SIZE,       0 },
+        { EGL_RED_SIZE,         0 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        5 },
+        { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
+        { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static configs_t const gConfigs[] = {
+        { config_0_attribute_list, NELEM(config_0_attribute_list) },
+        { config_1_attribute_list, NELEM(config_1_attribute_list) },
+        { config_2_attribute_list, NELEM(config_2_attribute_list) },
+        { config_3_attribute_list, NELEM(config_3_attribute_list) },
+        { config_4_attribute_list, NELEM(config_4_attribute_list) },
+        { config_5_attribute_list, NELEM(config_5_attribute_list) },
+        //   { config_6_attribute_list, NELEM(config_6_attribute_list) },
+        //   { config_7_attribute_list, NELEM(config_7_attribute_list) },
+};
+
+static config_management_t const gConfigManagement[] = {
+        { EGL_BUFFER_SIZE,                config_management_t::atLeast },
+        { EGL_ALPHA_SIZE,                 config_management_t::atLeast },
+        { EGL_BLUE_SIZE,                  config_management_t::atLeast },
+        { EGL_GREEN_SIZE,                 config_management_t::atLeast },
+        { EGL_RED_SIZE,                   config_management_t::atLeast },
+        { EGL_DEPTH_SIZE,                 config_management_t::atLeast },
+        { EGL_STENCIL_SIZE,               config_management_t::atLeast },
+        { EGL_CONFIG_CAVEAT,              config_management_t::exact   },
+        { EGL_CONFIG_ID,                  config_management_t::exact   },
+        { EGL_LEVEL,                      config_management_t::exact   },
+        { EGL_MAX_PBUFFER_HEIGHT,         config_management_t::ignore   },
+        { EGL_MAX_PBUFFER_PIXELS,         config_management_t::ignore   },
+        { EGL_MAX_PBUFFER_WIDTH,          config_management_t::ignore   },
+        { EGL_NATIVE_RENDERABLE,          config_management_t::exact   },
+        { EGL_NATIVE_VISUAL_ID,           config_management_t::ignore   },
+        { EGL_NATIVE_VISUAL_TYPE,         config_management_t::exact   },
+        { EGL_SAMPLES,                    config_management_t::exact   },
+        { EGL_SAMPLE_BUFFERS,             config_management_t::exact   },
+        { EGL_SURFACE_TYPE,               config_management_t::mask    },
+        { EGL_TRANSPARENT_TYPE,           config_management_t::exact   },
+        { EGL_TRANSPARENT_BLUE_VALUE,     config_management_t::exact   },
+        { EGL_TRANSPARENT_GREEN_VALUE,    config_management_t::exact   },
+        { EGL_TRANSPARENT_RED_VALUE,      config_management_t::exact   },
+        { EGL_BIND_TO_TEXTURE_RGBA,       config_management_t::exact   },
+        { EGL_BIND_TO_TEXTURE_RGB,        config_management_t::exact   },
+        { EGL_MIN_SWAP_INTERVAL,          config_management_t::exact   },
+        { EGL_MAX_SWAP_INTERVAL,          config_management_t::exact   },
+        { EGL_LUMINANCE_SIZE,             config_management_t::atLeast },
+        { EGL_ALPHA_MASK_SIZE,            config_management_t::atLeast },
+        { EGL_COLOR_BUFFER_TYPE,          config_management_t::exact   },
+        { EGL_RENDERABLE_TYPE,            config_management_t::mask    },
+        { EGL_CONFORMANT,                 config_management_t::mask    }
+};
+
+
+static config_pair_t const config_defaults[] = {
+        // attributes that are not specified are simply ignored, if a particular
+        // one needs not be ignored, it must be specified here, eg:
+        // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
+};
+
+// ----------------------------------------------------------------------------
+
+static status_t getConfigFormatInfo(EGLint configID,
+        int32_t& pixelFormat, int32_t& depthFormat)
+{
+    switch (configID) {
+        case 0:
+            pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+            depthFormat = 0;
+            break;
+        case 1:
+            pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+            depthFormat = GGL_PIXEL_FORMAT_Z_32;
+            break;
+        case 2:
+            pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+            depthFormat = 0;
+            break;
+        case 3:
+            pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+            depthFormat = GGL_PIXEL_FORMAT_Z_32;
+            break;
+        case 4:
+            pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+            depthFormat = 0;
+            break;
+        case 5:
+            pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+            depthFormat = GGL_PIXEL_FORMAT_Z_32;
+            break;
+        case 6:
+            pixelFormat = GGL_PIXEL_FORMAT_A_8;
+            depthFormat = 0;
+            break;
+        case 7:
+            pixelFormat = GGL_PIXEL_FORMAT_A_8;
+            depthFormat = GGL_PIXEL_FORMAT_Z_32;
+            break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+template<typename T>
+static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
+{
+    while (first <= last) {
+        int mid = (first + last) / 2;
+        if (key > sortedArray[mid].key) {
+            first = mid + 1;
+        } else if (key < sortedArray[mid].key) {
+            last = mid - 1;
+        } else {
+            return mid;
+        }
+    }
+    return -1;
+}
+
+static int isAttributeMatching(int i, EGLint attr, EGLint val)
+{
+    // look for the attribute in all of our configs
+    config_pair_t const* configFound = gConfigs[i].array;
+    int index = binarySearch<config_pair_t>(
+            gConfigs[i].array,
+            0, gConfigs[i].size-1,
+            attr);
+    if (index < 0) {
+        configFound = config_base_attribute_list;
+        index = binarySearch<config_pair_t>(
+                config_base_attribute_list,
+                0, NELEM(config_base_attribute_list)-1,
+                attr);
+    }
+    if (index >= 0) {
+        // attribute found, check if this config could match
+        int cfgMgtIndex = binarySearch<config_management_t>(
+                gConfigManagement,
+                0, NELEM(gConfigManagement)-1,
+                attr);
+        if (cfgMgtIndex >= 0) {
+            bool match = gConfigManagement[cfgMgtIndex].match(
+                    val, configFound[index].value);
+            if (match) {
+                // this config matches
+                return 1;
+            }
+        } else {
+            // attribute not found. this should NEVER happen.
+        }
+    } else {
+        // error, this attribute doesn't exist
+    }
+    return 0;
+}
+
+static int makeCurrent(GLES2Context* gl)
+{
+    GLES2Context* current = (GLES2Context*)getGlThreadSpecific();
+    if (gl) {
+        egl_context_t* c = egl_context_t::context(gl);
+        if (c->flags & egl_context_t::IS_CURRENT) {
+            if (current != gl) {
+                // it is an error to set a context current, if it's already
+                // current to another thread
+                return -1;
+            }
+        } else {
+            if (current) {
+                // mark the current context as not current, and flush
+                glFlush();
+                egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
+            }
+        }
+        if (!(c->flags & egl_context_t::IS_CURRENT)) {
+            // The context is not current, make it current!
+            setGlThreadSpecific(gl);
+            c->flags |= egl_context_t::IS_CURRENT;
+        }
+    } else {
+        if (current) {
+            // mark the current context as not current, and flush
+            glFlush();
+            egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
+        }
+        // this thread has no context attached to it
+        setGlThreadSpecific(0);
+    }
+    return 0;
+}
+
+static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
+        EGLint attribute, EGLint *value)
+{
+    size_t numConfigs =  NELEM(gConfigs);
+    int index = (int)config;
+    if (uint32_t(index) >= numConfigs)
+        return setError(EGL_BAD_CONFIG, EGL_FALSE);
+
+    int attrIndex;
+    attrIndex = binarySearch<config_pair_t>(
+            gConfigs[index].array,
+            0, gConfigs[index].size-1,
+            attribute);
+    if (attrIndex>=0) {
+        *value = gConfigs[index].array[attrIndex].value;
+        return EGL_TRUE;
+    }
+
+    attrIndex = binarySearch<config_pair_t>(
+            config_base_attribute_list,
+            0, NELEM(config_base_attribute_list)-1,
+            attribute);
+    if (attrIndex>=0) {
+        *value = config_base_attribute_list[attrIndex].value;
+        return EGL_TRUE;
+    }
+    return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+}
+
+static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
+        NativeWindowType window, const EGLint *attrib_list)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+    if (window == 0)
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+    EGLint surfaceType;
+    if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+        return EGL_FALSE;
+
+    if (!(surfaceType & EGL_WINDOW_BIT))
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+    if (reinterpret_cast<ANativeWindow*>(window)->common.magic !=
+            ANDROID_NATIVE_WINDOW_MAGIC) {
+        return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+    }
+
+    EGLint configID;
+    if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+        return EGL_FALSE;
+
+    int32_t depthFormat;
+    int32_t pixelFormat;
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+    }
+
+    // FIXME: we don't have access to the pixelFormat here just yet.
+    // (it's possible that the surface is not fully initialized)
+    // maybe this should be done after the page-flip
+    //if (EGLint(info.format) != pixelFormat)
+    //    return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+    egl_surface_t* surface;
+    surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
+            reinterpret_cast<ANativeWindow*>(window));
+
+    if (!surface->initCheck()) {
+        // there was a problem in the ctor, the error
+        // flag has been set.
+        delete surface;
+        surface = 0;
+    }
+    return surface;
+}
+
+static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
+        NativePixmapType pixmap, const EGLint *attrib_list)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+    if (pixmap == 0)
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+    EGLint surfaceType;
+    if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+        return EGL_FALSE;
+
+    if (!(surfaceType & EGL_PIXMAP_BIT))
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+    if (reinterpret_cast<egl_native_pixmap_t*>(pixmap)->version !=
+            sizeof(egl_native_pixmap_t)) {
+        return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
+    }
+
+    EGLint configID;
+    if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+        return EGL_FALSE;
+
+    int32_t depthFormat;
+    int32_t pixelFormat;
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+    }
+
+    if (reinterpret_cast<egl_native_pixmap_t *>(pixmap)->format != pixelFormat)
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+    egl_surface_t* surface =
+            new egl_pixmap_surface_t(dpy, config, depthFormat,
+                    reinterpret_cast<egl_native_pixmap_t*>(pixmap));
+
+    if (!surface->initCheck()) {
+        // there was a problem in the ctor, the error
+        // flag has been set.
+        delete surface;
+        surface = 0;
+    }
+    return surface;
+}
+
+static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
+        const EGLint *attrib_list)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+
+    EGLint surfaceType;
+    if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+        return EGL_FALSE;
+
+    if (!(surfaceType & EGL_PBUFFER_BIT))
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+    EGLint configID;
+    if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+        return EGL_FALSE;
+
+    int32_t depthFormat;
+    int32_t pixelFormat;
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+        return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+    }
+
+    int32_t w = 0;
+    int32_t h = 0;
+    while (attrib_list[0]) {
+        if (attrib_list[0] == EGL_WIDTH)  w = attrib_list[1];
+        if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
+        attrib_list+=2;
+    }
+
+    egl_surface_t* surface =
+            new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
+
+    if (!surface->initCheck()) {
+        // there was a problem in the ctor, the error
+        // flag has been set.
+        delete surface;
+        surface = 0;
+    }
+    return surface;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+// Initialization
+// ----------------------------------------------------------------------------
+
+EGLDisplay eglGetDisplay(NativeDisplayType display)
+{
+    puts("agl2:eglGetDisplay");
+#ifndef HAVE_ANDROID_OS
+    // this just needs to be done once
+    if (gGLKey == -1) {
+        pthread_mutex_lock(&gInitMutex);
+        if (gGLKey == -1)
+            pthread_key_create(&gGLKey, NULL);
+        pthread_mutex_unlock(&gInitMutex);
+    }
+#endif
+    if (display == EGL_DEFAULT_DISPLAY) {
+        EGLDisplay dpy = (EGLDisplay)1;
+        egl_display_t& d = egl_display_t::get_display(dpy);
+        d.type = display;
+        return dpy;
+    }
+    return EGL_NO_DISPLAY;
+}
+
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+    puts("agl2:eglInitialize");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    EGLBoolean res = EGL_TRUE;
+    egl_display_t& d = egl_display_t::get_display(dpy);
+
+    if (android_atomic_inc(&d.initialized) == 0) {
+        // initialize stuff here if needed
+        //pthread_mutex_lock(&gInitMutex);
+        //pthread_mutex_unlock(&gInitMutex);
+    }
+
+    if (res == EGL_TRUE) {
+        if (major != NULL) *major = VERSION_MAJOR;
+        if (minor != NULL) *minor = VERSION_MINOR;
+    }
+    return res;
+}
+
+EGLBoolean eglTerminate(EGLDisplay dpy)
+{
+    puts("agl2:eglTerminate");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    EGLBoolean res = EGL_TRUE;
+    egl_display_t& d = egl_display_t::get_display(dpy);
+    if (android_atomic_dec(&d.initialized) == 1) {
+        // TODO: destroy all resources (surfaces, contexts, etc...)
+        //pthread_mutex_lock(&gInitMutex);
+        //pthread_mutex_unlock(&gInitMutex);
+    }
+    return res;
+}
+
+// ----------------------------------------------------------------------------
+// configuration
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglGetConfigs(   EGLDisplay dpy,
+        EGLConfig *configs,
+        EGLint config_size, EGLint *num_config)
+{
+    puts("agl2:eglGetConfigs");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    GLint numConfigs = NELEM(gConfigs);
+    if (!configs) {
+        *num_config = numConfigs;
+        return EGL_TRUE;
+    }
+    GLint i;
+    for (i=0 ; i<numConfigs && i<config_size ; i++) {
+        *configs++ = (EGLConfig)i;
+    }
+    *num_config = i;
+    return EGL_TRUE;
+}
+
+static const char * ATTRIBUTE_NAMES [] = {
+        "EGL_BUFFER_SIZE",
+        "EGL_ALPHA_SIZE",
+        "EGL_BLUE_SIZE",
+        "EGL_GREEN_SIZE",
+        "EGL_RED_SIZE",
+        "EGL_DEPTH_SIZE",
+        "EGL_STENCIL_SIZE",
+        "EGL_CONFIG_CAVEAT",
+        "EGL_CONFIG_ID",
+        "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",
+        "EGL_PRESERVED_RESOURCES",
+        "EGL_SAMPLES",
+        "EGL_SAMPLE_BUFFERS",
+        "EGL_SURFACE_TYPE",
+        "EGL_TRANSPARENT_TYPE",
+        "EGL_TRANSPARENT_BLUE_VALUE",
+        "EGL_TRANSPARENT_GREEN_VALUE",
+        "EGL_TRANSPARENT_RED_VALUE",
+        "EGL_NONE",   /* Attrib list terminator */
+        "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_RENDERABLE_TYPE",
+        "EGL_MATCH_NATIVE_PIXMAP",   /* Pseudo-attribute (not queryable) */
+        "EGL_CONFORMANT",
+};
+
+EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
+        EGLConfig *configs, EGLint config_size,
+        EGLint *num_config)
+{
+    puts("agl2:eglChooseConfig");
+    LOGD("\n***\n***\n agl2:LOGD eglChooseConfig \n***\n***\n");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    if (ggl_unlikely(num_config==0)) {
+        LOGD("\n***\n***\n num_config==0 \n***\n***\n");
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    if (ggl_unlikely(attrib_list==0)) {
+        /*
+         * A NULL attrib_list should be treated as though it was an empty
+         * one (terminated with EGL_NONE) as defined in
+         * section 3.4.1 "Querying Configurations" in the EGL specification.
+         */
+        LOGD("\n***\n***\n attrib_list==0 \n***\n***\n");
+        static const EGLint dummy = EGL_NONE;
+        attrib_list = &dummy;
+    }
+
+    for (const EGLint * attrib = attrib_list; *attrib != EGL_NONE; attrib += 2) {
+        LOGD("eglChooseConfig %s(%.4X): %d \n", ATTRIBUTE_NAMES[attrib[0] - EGL_BUFFER_SIZE], attrib[0], attrib[1]);
+        if (EGL_BUFFER_SIZE > attrib[0] || EGL_CONFORMANT < attrib[0])
+            LOGD("eglChooseConfig invalid config attrib: 0x%.4X=%d \n", attrib[0], attrib[1]);
+    }
+
+    int numAttributes = 0;
+    int numConfigs =  NELEM(gConfigs);
+    uint32_t possibleMatch = (1<<numConfigs)-1;
+    while (possibleMatch && *attrib_list != EGL_NONE) {
+        numAttributes++;
+        EGLint attr = *attrib_list++;
+        EGLint val  = *attrib_list++;
+        for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
+            if (!(possibleMatch & (1<<i)))
+                continue;
+            if (isAttributeMatching(i, attr, val) == 0) {
+                LOGD("!isAttributeMatching config(%d) %s=%d \n", i, ATTRIBUTE_NAMES[attr - EGL_BUFFER_SIZE], val);
+                possibleMatch &= ~(1<<i);
+            }
+        }
+    }
+
+    LOGD("eglChooseConfig possibleMatch=%.4X \n", possibleMatch);
+
+    // now, handle the attributes which have a useful default value
+    for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
+        // see if this attribute was specified, if not, apply its
+        // default value
+        if (binarySearch<config_pair_t>(
+                (config_pair_t const*)attrib_list,
+                0, numAttributes-1,
+                config_defaults[j].key) < 0) {
+            for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
+                if (!(possibleMatch & (1<<i)))
+                    continue;
+                if (isAttributeMatching(i,
+                        config_defaults[j].key,
+                        config_defaults[j].value) == 0) {
+                    possibleMatch &= ~(1<<i);
+                }
+            }
+        }
+    }
+
+    // return the configurations found
+    int n=0;
+    if (possibleMatch) {
+        if (configs) {
+            for (int i=0 ; config_size && i<numConfigs ; i++) {
+                if (possibleMatch & (1<<i)) {
+                    *configs++ = (EGLConfig)i;
+                    config_size--;
+                    n++;
+                }
+            }
+        } else {
+            for (int i=0 ; i<numConfigs ; i++) {
+                if (possibleMatch & (1<<i)) {
+                    n++;
+                }
+            }
+        }
+    }
+    *num_config = n;
+    LOGD("\n***\n***\n num_config==%d \n***\n***\n", *num_config);
+    return EGL_TRUE;
+}
+
+EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+        EGLint attribute, EGLint *value)
+{
+    puts("agl2:eglGetConfigAttrib");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    return getConfigAttrib(dpy, config, attribute, value);
+}
+
+// ----------------------------------------------------------------------------
+// surfaces
+// ----------------------------------------------------------------------------
+
+EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
+        NativeWindowType window,
+        const EGLint *attrib_list)
+{
+    puts("agl2:eglCreateWindowSurface");
+    return createWindowSurface(dpy, config, window, attrib_list);
+}
+
+EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
+        NativePixmapType pixmap,
+        const EGLint *attrib_list)
+{
+    puts("agl2:eglCreatePixmapSurface");
+    return createPixmapSurface(dpy, config, pixmap, attrib_list);
+}
+
+EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
+        const EGLint *attrib_list)
+{
+    puts("agl2:eglCreatePbufferSurface");
+    return createPbufferSurface(dpy, config, attrib_list);
+}
+
+EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
+{
+    puts("agl2:eglDestroySurface");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    if (eglSurface != EGL_NO_SURFACE) {
+        egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
+        if (!surface->isValid())
+            return setError(EGL_BAD_SURFACE, EGL_FALSE);
+        if (surface->dpy != dpy)
+            return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+        if (surface->ctx) {
+            // FIXME: this surface is current check what the spec says
+            surface->disconnect();
+            surface->ctx = 0;
+        }
+        delete surface;
+    }
+    return EGL_TRUE;
+}
+
+EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
+        EGLint attribute, EGLint *value)
+{
+    puts("agl2:eglQuerySurface");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
+    if (!surface->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    if (surface->dpy != dpy)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    EGLBoolean ret = EGL_TRUE;
+    switch (attribute) {
+        case EGL_CONFIG_ID:
+            ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
+            break;
+        case EGL_WIDTH:
+            *value = surface->getWidth();
+            break;
+        case EGL_HEIGHT:
+            *value = surface->getHeight();
+            break;
+        case EGL_LARGEST_PBUFFER:
+            // not modified for a window or pixmap surface
+            break;
+        case EGL_TEXTURE_FORMAT:
+            *value = EGL_NO_TEXTURE;
+            break;
+        case EGL_TEXTURE_TARGET:
+            *value = EGL_NO_TEXTURE;
+            break;
+        case EGL_MIPMAP_TEXTURE:
+            *value = EGL_FALSE;
+            break;
+        case EGL_MIPMAP_LEVEL:
+            *value = 0;
+            break;
+        case EGL_RENDER_BUFFER:
+            // TODO: return the real RENDER_BUFFER here
+            *value = EGL_BACK_BUFFER;
+            break;
+        case EGL_HORIZONTAL_RESOLUTION:
+            // pixel/mm * EGL_DISPLAY_SCALING
+            *value = surface->getHorizontalResolution();
+            break;
+        case EGL_VERTICAL_RESOLUTION:
+            // pixel/mm * EGL_DISPLAY_SCALING
+            *value = surface->getVerticalResolution();
+            break;
+        case EGL_PIXEL_ASPECT_RATIO: {
+            // w/h * EGL_DISPLAY_SCALING
+            int wr = surface->getHorizontalResolution();
+            int hr = surface->getVerticalResolution();
+            *value = (wr * EGL_DISPLAY_SCALING) / hr;
+        }
+        break;
+        case EGL_SWAP_BEHAVIOR:
+            *value = surface->getSwapBehavior();
+            break;
+        default:
+            ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+    }
+    return ret;
+}
+
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
+        EGLContext share_list, const EGLint *attrib_list)
+{
+    puts("agl2:eglCreateContext");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+
+    GLES2Context* gl = new GLES2Context();//ogles_init(sizeof(egl_context_t));
+    if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+
+    //egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
+    egl_context_t * c = &gl->egl;
+    c->flags = egl_context_t::NEVER_CURRENT;
+    c->dpy = dpy;
+    c->config = config;
+    c->read = 0;
+    c->draw = 0;
+
+    c->frame = 0;
+    c->lastSwapTime = clock();
+    c->accumulateSeconds = 0;
+    return (EGLContext)gl;
+}
+
+EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+    puts("agl2:eglDestroyContext");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    egl_context_t* c = egl_context_t::context(ctx);
+    if (c->flags & egl_context_t::IS_CURRENT)
+        setGlThreadSpecific(0);
+    //ogles_uninit((GLES2Context*)ctx);
+    delete (GLES2Context*)ctx;
+    return EGL_TRUE;
+}
+
+EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
+        EGLSurface read, EGLContext ctx)
+{
+    puts("agl2:eglMakeCurrent");
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    if (draw) {
+        egl_surface_t* s = (egl_surface_t*)draw;
+        if (!s->isValid())
+            return setError(EGL_BAD_SURFACE, EGL_FALSE);
+        if (s->dpy != dpy)
+            return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+        // TODO: check that draw is compatible with the context
+    }
+    if (read && read!=draw) {
+        egl_surface_t* s = (egl_surface_t*)read;
+        if (!s->isValid())
+            return setError(EGL_BAD_SURFACE, EGL_FALSE);
+        if (s->dpy != dpy)
+            return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+        // TODO: check that read is compatible with the context
+    }
+
+    EGLContext current_ctx = EGL_NO_CONTEXT;
+
+    if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
+        return setError(EGL_BAD_MATCH, EGL_FALSE);
+
+    if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
+        return setError(EGL_BAD_MATCH, EGL_FALSE);
+
+    if (ctx == EGL_NO_CONTEXT) {
+        // if we're detaching, we need the current context
+        current_ctx = (EGLContext)getGlThreadSpecific();
+    } else {
+        egl_context_t* c = egl_context_t::context(ctx);
+        egl_surface_t* d = (egl_surface_t*)draw;
+        egl_surface_t* r = (egl_surface_t*)read;
+        if ((d && d->ctx && d->ctx != ctx) ||
+                (r && r->ctx && r->ctx != ctx)) {
+            // one of the surface is bound to a context in another thread
+            return setError(EGL_BAD_ACCESS, EGL_FALSE);
+        }
+    }
+
+    GLES2Context* gl = (GLES2Context*)ctx;
+    if (makeCurrent(gl) == 0) {
+        if (ctx) {
+            egl_context_t* c = egl_context_t::context(ctx);
+            egl_surface_t* d = (egl_surface_t*)draw;
+            egl_surface_t* r = (egl_surface_t*)read;
+
+            if (c->draw) {
+                egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
+                s->disconnect();
+            }
+            if (c->read) {
+                // FIXME: unlock/disconnect the read surface too
+            }
+
+            c->draw = draw;
+            c->read = read;
+
+            if (c->flags & egl_context_t::NEVER_CURRENT) {
+                c->flags &= ~egl_context_t::NEVER_CURRENT;
+                GLint w = 0;
+                GLint h = 0;
+                if (draw) {
+                    w = d->getWidth();
+                    h = d->getHeight();
+                }
+                gl->rasterizer.interface.Viewport(&gl->rasterizer.interface, 0, 0, w, h);
+                //ogles_surfaceport(gl, 0, 0);
+                //ogles_viewport(gl, 0, 0, w, h);
+                //ogles_scissor(gl, 0, 0, w, h);
+            }
+            if (d) {
+                if (d->connect() == EGL_FALSE) {
+                    return EGL_FALSE;
+                }
+                d->ctx = ctx;
+                d->bindDrawSurface(gl);
+            }
+            if (r) {
+                // FIXME: lock/connect the read surface too
+                r->ctx = ctx;
+                r->bindReadSurface(gl);
+            }
+        } else {
+            // if surfaces were bound to the context bound to this thread
+            // mark then as unbound.
+            if (current_ctx) {
+                egl_context_t* c = egl_context_t::context(current_ctx);
+                egl_surface_t* d = (egl_surface_t*)c->draw;
+                egl_surface_t* r = (egl_surface_t*)c->read;
+                if (d) {
+                    c->draw = 0;
+                    d->ctx = EGL_NO_CONTEXT;
+                    d->disconnect();
+                }
+                if (r) {
+                    c->read = 0;
+                    r->ctx = EGL_NO_CONTEXT;
+                    // FIXME: unlock/disconnect the read surface too
+                }
+            }
+        }
+        return EGL_TRUE;
+    }
+    return setError(EGL_BAD_ACCESS, EGL_FALSE);
+}
+
+EGLContext eglGetCurrentContext(void)
+{
+    // eglGetCurrentContext returns the current EGL rendering context,
+    // as specified by eglMakeCurrent. If no context is current,
+    // EGL_NO_CONTEXT is returned.
+    return (EGLContext)getGlThreadSpecific();
+}
+
+EGLSurface eglGetCurrentSurface(EGLint readdraw)
+{
+    // eglGetCurrentSurface returns the read or draw surface attached
+    // to the current EGL rendering context, as specified by eglMakeCurrent.
+    // If no context is current, EGL_NO_SURFACE is returned.
+    EGLContext ctx = (EGLContext)getGlThreadSpecific();
+    if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
+    egl_context_t* c = egl_context_t::context(ctx);
+    if (readdraw == EGL_READ) {
+        return c->read;
+    } else if (readdraw == EGL_DRAW) {
+        return c->draw;
+    }
+    return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+}
+
+EGLDisplay eglGetCurrentDisplay(void)
+{
+    // eglGetCurrentDisplay returns the current EGL display connection
+    // for the current EGL rendering context, as specified by eglMakeCurrent.
+    // If no context is current, EGL_NO_DISPLAY is returned.
+    EGLContext ctx = (EGLContext)getGlThreadSpecific();
+    if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
+    egl_context_t* c = egl_context_t::context(ctx);
+    return c->dpy;
+}
+
+EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
+        EGLint attribute, EGLint *value)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    egl_context_t* c = egl_context_t::context(ctx);
+    switch (attribute) {
+        case EGL_CONFIG_ID:
+            // Returns the ID of the EGL frame buffer configuration with
+            // respect to which the context was created
+            return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
+    }
+    return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+}
+
+EGLBoolean eglWaitGL(void)
+{
+    return EGL_TRUE;
+}
+
+EGLBoolean eglWaitNative(EGLint engine)
+{
+    return EGL_TRUE;
+}
+
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+    if (!d->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    if (d->dpy != dpy)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    // post the surface
+    d->swapBuffers();
+
+    // if it's bound to a context, update the buffer
+    if (d->ctx != EGL_NO_CONTEXT) {
+        d->bindDrawSurface((GLES2Context*)d->ctx);
+        // if this surface is also the read surface of the context
+        // it is bound to, make sure to update the read buffer as well.
+        // The EGL spec is a little unclear about this.
+        egl_context_t* c = egl_context_t::context(d->ctx);
+        if (c->read == draw) {
+            d->bindReadSurface((GLES2Context*)d->ctx);
+        }
+        clock_t time = clock();
+        float elapsed = (float)(time - c->lastSwapTime) / CLOCKS_PER_SEC;
+        c->accumulateSeconds += elapsed;
+        c->frame++;
+        //      LOGD("agl2: eglSwapBuffers elapsed=%.2fms \n*", elapsed * 1000);
+        if (20 == c->frame) {
+            float avg = c->accumulateSeconds / c->frame;
+            LOGD("\n*\n* agl2: eglSwapBuffers %u frame avg fps=%.1f elapsed=%.2fms \n*",
+                    c->frame, 1 / avg, avg * 1000);
+            c->frame = 0;
+            c->accumulateSeconds = 0;
+        }
+        c->lastSwapTime = time;
+    }
+
+    return EGL_TRUE;
+}
+
+EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
+        NativePixmapType target)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    // TODO: eglCopyBuffers()
+    return EGL_FALSE;
+}
+
+EGLint eglGetError(void)
+{
+    return getError();
+}
+
+const char* eglQueryString(EGLDisplay dpy, EGLint name)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, (const char*)0);
+
+    switch (name) {
+        case EGL_VENDOR:
+            return gVendorString;
+        case EGL_VERSION:
+            return gVersionString;
+        case EGL_EXTENSIONS:
+            return gExtensionsString;
+        case EGL_CLIENT_APIS:
+            return gClientApiString;
+    }
+    return setError(EGL_BAD_PARAMETER, (const char *)0);
+}
+
+// ----------------------------------------------------------------------------
+// EGL 1.1
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSurfaceAttrib(
+        EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    // TODO: eglSurfaceAttrib()
+    return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+}
+
+EGLBoolean eglBindTexImage(
+        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    // TODO: eglBindTexImage()
+    return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+}
+
+EGLBoolean eglReleaseTexImage(
+        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    // TODO: eglReleaseTexImage()
+    return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+}
+
+EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    // TODO: eglSwapInterval()
+    return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// EGL 1.2
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglBindAPI(EGLenum api)
+{
+    if (api != EGL_OPENGL_ES_API)
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    return EGL_TRUE;
+}
+
+EGLenum eglQueryAPI(void)
+{
+    return EGL_OPENGL_ES_API;
+}
+
+EGLBoolean eglWaitClient(void)
+{
+    glFinish();
+    return EGL_TRUE;
+}
+
+EGLBoolean eglReleaseThread(void)
+{
+    // TODO: eglReleaseThread()
+    return EGL_TRUE;
+}
+
+EGLSurface eglCreatePbufferFromClientBuffer(
+        EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+        EGLConfig config, const EGLint *attrib_list)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+    // TODO: eglCreatePbufferFromClientBuffer()
+    return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+}
+
+// ----------------------------------------------------------------------------
+// EGL_EGLEXT_VERSION 3
+// ----------------------------------------------------------------------------
+
+void (*eglGetProcAddress (const char *procname))()
+        {
+    extention_map_t const * const map = gExtentionMap;
+    for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
+        if (!strcmp(procname, map[i].name)) {
+            return map[i].address;
+        }
+    }
+    return NULL;
+        }
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+        const EGLint *attrib_list)
+{
+    EGLBoolean result = EGL_FALSE;
+    return result;
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+{
+    EGLBoolean result = EGL_FALSE;
+    return result;
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+        EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+        return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
+    }
+    if (ctx != EGL_NO_CONTEXT) {
+        return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+    }
+    if (target != EGL_NATIVE_BUFFER_ANDROID) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+    }
+
+    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)buffer;
+
+    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+    if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
+        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+    switch (native_buffer->format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            break;
+        default:
+            return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+    }
+
+    native_buffer->common.incRef(&native_buffer->common);
+    return (EGLImageKHR)native_buffer;
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    }
+
+    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)img;
+
+    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+    if (native_buffer->common.version != sizeof(ANativeWindowBuffer))
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+    native_buffer->common.decRef(&native_buffer->common);
+
+    return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// ANDROID extensions
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
+        EGLint left, EGLint top, EGLint width, EGLint height)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+    if (!d->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    if (d->dpy != dpy)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    // post the surface
+    d->setSwapRectangle(left, top, width, height);
+
+    return EGL_TRUE;
+}
diff --git a/opengl/libagl2/src/get.cpp b/opengl/libagl2/src/get.cpp
new file mode 100644
index 0000000..13c28ce
--- /dev/null
+++ b/opengl/libagl2/src/get.cpp
@@ -0,0 +1,79 @@
+#include "gles2context.h"
+
+static char const * const gVendorString     = "Android";
+static char const * const gRendererString   = "Android PixelFlinger2 0.0";
+static char const * const gVersionString    = "OpenGL ES 2.0";
+static char const * const gExtensionsString =
+//   "GL_OES_byte_coordinates "              // OK
+//   "GL_OES_fixed_point "                   // OK
+//   "GL_OES_single_precision "              // OK
+//   "GL_OES_read_format "                   // OK
+//   "GL_OES_compressed_paletted_texture "   // OK
+//   "GL_OES_draw_texture "                  // OK
+//   "GL_OES_matrix_get "                    // OK
+//   "GL_OES_query_matrix "                  // OK
+//   //        "GL_OES_point_size_array "              // TODO
+//   //        "GL_OES_point_sprite "                  // TODO
+//   "GL_OES_EGL_image "                     // OK
+//#ifdef GL_OES_compressed_ETC1_RGB8_texture
+//   "GL_OES_compressed_ETC1_RGB8_texture "  // OK
+//#endif
+//   "GL_ARB_texture_compression "           // OK
+//   "GL_ARB_texture_non_power_of_two "      // OK
+//   "GL_ANDROID_user_clip_plane "           // OK
+//   "GL_ANDROID_vertex_buffer_object "      // OK
+//   "GL_ANDROID_generate_mipmap "           // OK
+   ""
+   ;
+
+void glGetIntegerv(GLenum pname, GLint* params)
+{
+   switch (pname) {
+   case GL_MAX_TEXTURE_SIZE :
+      *params = 4096; // limit is in precision of texcoord calculation, which uses 16.16
+      break;
+   case GL_MAX_VERTEX_ATTRIBS:
+      *params = GGL_MAXVERTEXATTRIBS;
+      break;
+   case GL_MAX_VERTEX_UNIFORM_VECTORS:
+      *params = GGL_MAXVERTEXUNIFORMVECTORS;
+      break;
+   case GL_MAX_VARYING_VECTORS:
+      *params = GGL_MAXVARYINGVECTORS;
+      break;
+   case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+      *params = GGL_MAXCOMBINEDTEXTUREIMAGEUNITS;
+      break;
+   case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+      *params = GGL_MAXVERTEXTEXTUREIMAGEUNITS;
+      break;
+   case GL_MAX_TEXTURE_IMAGE_UNITS:
+      *params = GGL_MAXTEXTUREIMAGEUNITS;
+      break;
+   case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+      *params = GGL_MAXFRAGMENTUNIFORMVECTORS;
+      break;
+   case GL_ALIASED_LINE_WIDTH_RANGE:
+      *params = 1; // TODO: not implemented
+      break;
+   default:
+      LOGD("agl2: glGetIntegerv 0x%.4X", pname);
+      assert(0);
+   }
+}
+
+const GLubyte* glGetString(GLenum name)
+{
+   switch (name) {
+   case GL_VENDOR:
+      return (const GLubyte*)gVendorString;
+   case GL_RENDERER:
+      return (const GLubyte*)gRendererString;
+   case GL_VERSION:
+      return (const GLubyte*)gVersionString;
+   case GL_EXTENSIONS:
+      return (const GLubyte*)gExtensionsString;
+   }
+   assert(0); //(c, GL_INVALID_ENUM);
+   return 0;
+}
diff --git a/opengl/libagl2/src/gles2context.h b/opengl/libagl2/src/gles2context.h
new file mode 100644
index 0000000..cec0340
--- /dev/null
+++ b/opengl/libagl2/src/gles2context.h
@@ -0,0 +1,166 @@
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/threads.h>
+#include <pthread.h>
+
+#include <cutils/log.h>
+
+#include <assert.h>
+
+#ifdef __arm__
+#ifndef __location__
+#define __HIERALLOC_STRING_0__(s)   #s
+#define __HIERALLOC_STRING_1__(s)   __HIERALLOC_STRING_0__(s)
+#define __HIERALLOC_STRING_2__      __HIERALLOC_STRING_1__(__LINE__)
+#define __location__                __FILE__ ":" __HIERALLOC_STRING_2__
+#endif
+#undef assert
+#define assert(EXPR) { do { if (!(EXPR)) {LOGD("\n*\n*\n*\n* assert fail: '"#EXPR"' at "__location__"\n*\n*\n*\n*"); exit(EXIT_FAILURE); } } while (false); }
+//#define printf LOGD
+#else // #ifdef __arm__
+//#define LOGD printf
+#endif // #ifdef __arm__
+
+
+#include <pixelflinger2/pixelflinger2_format.h>
+#include <pixelflinger2/pixelflinger2.h>
+
+#include <map>
+
+typedef uint8_t                 GGLubyte;               // ub
+
+#define ggl_likely(x)   __builtin_expect(!!(x), 1)
+#define ggl_unlikely(x) __builtin_expect(!!(x), 0)
+
+#undef NELEM
+#define NELEM(x) (sizeof(x)/sizeof(*(x)))
+
+template<typename T>
+inline T max(T a, T b)
+{
+   return a<b ? b : a;
+}
+
+template<typename T>
+inline T min(T a, T b)
+{
+   return a<b ? a : b;
+}
+
+struct egl_context_t {
+   enum {
+      IS_CURRENT      =   0x00010000,
+      NEVER_CURRENT   =   0x00020000
+   };
+   uint32_t            flags;
+   EGLDisplay          dpy;
+   EGLConfig           config;
+   EGLSurface          read;
+   EGLSurface          draw;
+
+   unsigned frame;
+   clock_t lastSwapTime;
+   float accumulateSeconds;
+   
+   static inline egl_context_t* context(EGLContext ctx);
+};
+
+struct GLES2Context;
+
+#ifdef HAVE_ANDROID_OS
+#include <bionic_tls.h>
+// We have a dedicated TLS slot in bionic
+inline void setGlThreadSpecific(GLES2Context *value)
+{
+   ((uint32_t *)__get_tls())[TLS_SLOT_OPENGL] = (uint32_t)value;
+}
+inline GLES2Context* getGlThreadSpecific()
+{
+   return (GLES2Context *)(((unsigned *)__get_tls())[TLS_SLOT_OPENGL]);
+}
+#else
+extern pthread_key_t gGLKey;
+inline void setGlThreadSpecific(GLES2Context *value)
+{
+   pthread_setspecific(gGLKey, value);
+}
+inline GLES2Context* getGlThreadSpecific()
+{
+   return static_cast<GLES2Context*>(pthread_getspecific(gGLKey));
+}
+#endif
+
+struct VBO {
+   unsigned size;
+   GLenum usage;
+   void * data;
+};
+
+struct GLES2Context {
+   GGLContext rasterizer;
+   egl_context_t egl;
+   GGLInterface * iface; // shortcut to &rasterizer.interface
+
+   struct VertexState {
+      struct VertAttribPointer {
+         unsigned size; // number of values per vertex
+         GLenum type;  // data type
+         unsigned stride; // bytes
+         const void * ptr;
+bool normalized :
+         1;
+bool enabled :
+         1;
+      } attribs [GGL_MAXVERTEXATTRIBS];
+
+      VBO * vbo, * indices;
+      std::map<GLuint, VBO *> vbos;
+      GLuint free;
+
+      Vector4 defaultAttribs [GGL_MAXVERTEXATTRIBS];
+   } vert;
+
+   struct TextureState {
+      GGLTexture * tmus[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS];
+      int sampler2tmu[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS]; // sampler2tmu[sampler] is index of tmu, -1 means not used
+      unsigned active;
+      std::map<GLuint, GGLTexture *> textures;
+      GLuint free; // first possible free name
+      GGLTexture * tex2D, * texCube; // default textures
+      unsigned unpack;
+      
+      void UpdateSampler(GGLInterface * iface, unsigned tmu);
+   } tex;
+
+   GLES2Context();
+   void InitializeTextures();
+   void InitializeVertices();
+
+   ~GLES2Context();
+   void UninitializeTextures();
+   void UninitializeVertices();
+
+   static inline GLES2Context* get() {
+      return getGlThreadSpecific();
+   }
+};
+
+inline egl_context_t* egl_context_t::context(EGLContext ctx)
+{
+   GLES2Context* const gl = static_cast<GLES2Context*>(ctx);
+   return static_cast<egl_context_t*>(&gl->egl);
+}
+
+#define GLES2_GET_CONTEXT(ctx) GLES2Context * ctx = GLES2Context::get(); \
+                                 /*puts(__FUNCTION__);*/
+#define GLES2_GET_CONST_CONTEXT(ctx) GLES2Context * ctx = GLES2Context::get(); \
+                                       /*puts(__FUNCTION__);*/
diff --git a/opengl/libagl2/src/shader.cpp b/opengl/libagl2/src/shader.cpp
new file mode 100644
index 0000000..076e388
--- /dev/null
+++ b/opengl/libagl2/src/shader.cpp
@@ -0,0 +1,191 @@
+#include "gles2context.h"
+
+//#undef LOGD
+//#define LOGD(...)
+
+static inline GLuint s2n(gl_shader * s)
+{
+   return (GLuint)s ^ 0xaf3c532d;
+}
+
+static inline gl_shader * n2s(GLuint n)
+{
+   return (gl_shader *)(n ^ 0xaf3c532d);
+}
+
+static inline GLuint p2n(gl_shader_program * p)
+{
+   return (GLuint)p ^ 0x04dc18f9;
+}
+
+static inline gl_shader_program * n2p(GLuint n)
+{
+   return (gl_shader_program *)(n ^ 0x04dc18f9);
+}
+
+void glAttachShader(GLuint program, GLuint shader)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderAttach(ctx->iface, n2p(program), n2s(shader));
+}
+
+void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderAttributeBind(n2p(program), index, name);
+//   assert(0);
+}
+
+GLuint glCreateShader(GLenum type)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   return s2n(ctx->iface->ShaderCreate(ctx->iface, type));
+}
+
+GLuint glCreateProgram(void)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   return  p2n(ctx->iface->ShaderProgramCreate(ctx->iface));
+}
+
+void glCompileShader(GLuint shader)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderCompile(ctx->iface, n2s(shader), NULL, NULL);
+}
+
+void glDeleteProgram(GLuint program)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderProgramDelete(ctx->iface, n2p(program));
+}
+
+void glDeleteShader(GLuint shader)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderDelete(ctx->iface, n2s(shader));
+}
+
+void glDetachShader(GLuint program, GLuint shader)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderDetach(ctx->iface, n2p(program), n2s(shader));
+}
+
+GLint glGetAttribLocation(GLuint program, const GLchar* name)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   GLint location = ctx->iface->ShaderAttributeLocation(n2p(program), name);
+//   LOGD("\n*\n*\n* agl2: glGetAttribLocation program=%u name=%s location=%d \n*\n*",
+//        program, name, location);
+   return location;
+}
+
+void glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderProgramGetiv(n2p(program), pname, params);
+   LOGD("agl2: glGetProgramiv 0x%.4X=%d \n", pname, *params);
+}
+
+void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderProgramGetInfoLog(n2p(program), bufsize, length, infolog);
+}
+
+void glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderGetiv(n2s(shader), pname, params);
+   LOGD("agl2: glGetShaderiv 0x%.4X=%d \n", pname, *params);
+}
+
+void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderGetInfoLog(n2s(shader), bufsize, length, infolog);
+}
+
+int glGetUniformLocation(GLuint program, const GLchar* name)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   return ctx->iface->ShaderUniformLocation(n2p(program), name);
+}
+
+void glLinkProgram(GLuint program)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   GLboolean linked = ctx->iface->ShaderProgramLink(n2p(program), NULL);
+   assert(linked);
+}
+
+void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderSource(n2s(shader), count, string, length);
+}
+
+void glUniform1f(GLint location, GLfloat x)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   int sampler = ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, &x, GL_FLOAT);
+   assert(0 > sampler); // should be assigning to sampler
+}
+
+void glUniform1i(GLint location, GLint x)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   const float params[1] = {x};
+   int sampler = ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_INT);
+   if (0 <= sampler) {
+//      LOGD("\n*\n* agl2: glUniform1i updated sampler=%d tmu=%d location=%d\n*", sampler, x, location);
+      assert(0 <= x && GGL_MAXCOMBINEDTEXTUREIMAGEUNITS > x);
+//      LOGD("tmu%u: format=0x%.2X w=%u h=%u levels=%p", x, ctx->tex.tmus[x]->format, 
+//         ctx->tex.tmus[x]->width, ctx->tex.tmus[x]->height, ctx->tex.tmus[x]->format);
+      ctx->tex.sampler2tmu[sampler] = x;
+      ctx->tex.UpdateSampler(ctx->iface, x);
+   }
+}
+
+void glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   const float params[4] = {x, y};
+   ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_FLOAT_VEC2);
+}
+
+void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   const float params[4] = {x, y, z, w};
+//   LOGD("agl2: glUniform4f location=%d %f,%f,%f,%f", location, x, y, z, w);
+   ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_FLOAT_VEC4);
+}
+
+void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   const gl_shader_program * program = ctx->rasterizer.CurrentProgram;
+//   if (strstr(program->Shaders[MESA_SHADER_FRAGMENT]->Source, ").a;")) {
+//   LOGD("agl2: glUniformMatrix4fv location=%d count=%d transpose=%d", location, count, transpose);
+//   for (unsigned i = 0; i < 4; i++)
+//      LOGD("agl2: glUniformMatrix4fv %.2f \t %.2f \t %.2f \t %.2f", value[i * 4 + 0],
+//           value[i * 4 + 1], value[i * 4 + 2], value[i * 4 + 3]);
+//   }
+   ctx->iface->ShaderUniformMatrix(ctx->rasterizer.CurrentProgram, 4, 4, location, count, transpose, value);
+//   while (true)
+//      ;
+//   assert(0);
+}
+
+void glUseProgram(GLuint program)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("\n*\n*\n* agl2: glUseProgram %d \n*\n*\n*", program);
+   ctx->iface->ShaderUse(ctx->iface, n2p(program));
+   ctx->iface->ShaderUniformGetSamplers(n2p(program), ctx->tex.sampler2tmu);
+   for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
+      if (0 <= ctx->tex.sampler2tmu[i])
+         ctx->iface->SetSampler(ctx->iface, i, ctx->tex.tmus[ctx->tex.sampler2tmu[i]]);
+}
diff --git a/opengl/libagl2/src/state.cpp b/opengl/libagl2/src/state.cpp
new file mode 100644
index 0000000..22e73fa
--- /dev/null
+++ b/opengl/libagl2/src/state.cpp
@@ -0,0 +1,129 @@
+#include "gles2context.h"
+
+GLES2Context::GLES2Context()
+{
+   memset(this, 0, sizeof *this);
+
+   assert((void *)&rasterizer == &rasterizer.interface);
+   InitializeGGLState(&rasterizer.interface);
+   iface = &rasterizer.interface;
+   printf("gl->rasterizer.PickScanLine(%p) = %p \n", &rasterizer.PickScanLine, rasterizer.PickScanLine);
+   assert(rasterizer.PickRaster);
+   assert(rasterizer.PickScanLine);
+
+   InitializeTextures();
+   InitializeVertices();
+}
+
+GLES2Context::~GLES2Context()
+{
+   UninitializeTextures();
+   UninitializeVertices();
+   UninitializeGGLState(&rasterizer.interface);
+}
+
+void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendColor(ctx->iface, red, green, blue, alpha);
+}
+
+void glBlendEquation( GLenum mode )
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendEquationSeparate(ctx->iface, mode, mode);
+}
+
+void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendEquationSeparate(ctx->iface, modeRGB, modeAlpha);
+}
+
+void glBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendFuncSeparate(ctx->iface, sfactor, dfactor, sfactor, dfactor);
+}
+
+void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendFuncSeparate(ctx->iface, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void glClear(GLbitfield mask)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->Clear(ctx->iface, mask);
+}
+
+void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ClearColor(ctx->iface, red, green, blue, alpha);
+}
+
+void glClearDepthf(GLclampf depth)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ClearDepthf(ctx->iface, depth);
+}
+
+void glClearStencil(GLint s)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ClearStencil(ctx->iface, s);
+}
+
+void glCullFace(GLenum mode)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->CullFace(ctx->iface, mode);
+}
+
+void glDisable(GLenum cap)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->EnableDisable(ctx->iface, cap, false);
+}
+
+void glEnable(GLenum cap)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->EnableDisable(ctx->iface, cap, true);
+}
+
+void glFinish(void)
+{
+   // do nothing
+}
+
+void glFrontFace(GLenum mode)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->FrontFace(ctx->iface, mode);
+}
+
+void glFlush(void)
+{
+   // do nothing
+}
+
+void glHint(GLenum target, GLenum mode)
+{
+   // do nothing
+}
+
+void glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+//   LOGD("agl2: glScissor not implemented x=%d y=%d width=%d height=%d", x, y, width, height);
+   //CALL_GL_API(glScissor, x, y, width, height);
+}
+
+void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glViewport x=%d y=%d width=%d height=%d", x, y, width, height);
+   ctx->iface->Viewport(ctx->iface, x, y, width, height);
+}
diff --git a/opengl/libagl2/src/texture.cpp b/opengl/libagl2/src/texture.cpp
new file mode 100644
index 0000000..4de1f16
--- /dev/null
+++ b/opengl/libagl2/src/texture.cpp
@@ -0,0 +1,534 @@
+#include "gles2context.h"
+
+//#undef LOGD
+//#define LOGD(...) 
+
+#define API_ENTRY
+#define CALL_GL_API(NAME,...) LOGD("?"#NAME); assert(0);
+#define CALL_GL_API_RETURN(NAME,...) LOGD("?"#NAME); assert(0); return 0;
+
+static inline GGLTexture * AllocTexture()
+{
+   GGLTexture * tex = (GGLTexture *)calloc(1, sizeof(GGLTexture));
+   tex->minFilter = GGLTexture::GGL_LINEAR; // should be NEAREST_ MIPMAP_LINEAR
+   tex->magFilter = GGLTexture::GGL_LINEAR;
+   return tex;
+}
+
+void GLES2Context::InitializeTextures()
+{
+   tex.textures = std::map<GLuint, GGLTexture *>(); // the entire struct has been zeroed in constructor
+   tex.tex2D = AllocTexture();
+   tex.textures[GL_TEXTURE_2D] = tex.tex2D;
+   tex.texCube = AllocTexture();
+   tex.textures[GL_TEXTURE_CUBE_MAP] = tex.texCube;
+   for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) {
+      tex.tmus[i] = NULL;
+      tex.sampler2tmu[i] = NULL;
+   }
+
+   tex.active = 0;
+
+   tex.free = max(GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP) + 1;
+
+   tex.tex2D->format = GGL_PIXEL_FORMAT_RGBA_8888;
+   tex.tex2D->type = GL_TEXTURE_2D;
+   tex.tex2D->levelCount = 1;
+   tex.tex2D->wrapS = tex.tex2D->wrapT = GGLTexture::GGL_REPEAT;
+   tex.tex2D->minFilter = tex.tex2D->magFilter = GGLTexture::GGL_NEAREST;
+   tex.tex2D->width = tex.tex2D->height = 1;
+   tex.tex2D->levels = malloc(4);
+   *(unsigned *)tex.tex2D->levels = 0xff000000;
+
+
+   tex.texCube->format = GGL_PIXEL_FORMAT_RGBA_8888;
+   tex.texCube->type = GL_TEXTURE_CUBE_MAP;
+   tex.texCube->levelCount = 1;
+   tex.texCube->wrapS = tex.texCube->wrapT = GGLTexture::GGL_REPEAT;
+   tex.texCube->minFilter = tex.texCube->magFilter = GGLTexture::GGL_NEAREST;
+   tex.texCube->width = tex.texCube->height = 1;
+   tex.texCube->levels = malloc(4 * 6);
+   static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000,
+                                 0xff00ffff, 0xffffff00, 0xffff00ff
+                                };
+   memcpy(tex.texCube->levels, texels, sizeof texels);
+
+   //texture.levelCount = GenerateMipmaps(texture.levels, texture.width, texture.height);
+
+   //    static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000,
+   //    0xff00ffff, 0xffffff00, 0xffff00ff};
+   //    memcpy(texture.levels[0], texels, sizeof texels);
+   //    texture.format = GGL_PIXEL_FORMAT_RGBA_8888;
+   //    texture.width = texture.height = 1;
+   //texture.height /= 6;
+   //texture.type = GL_TEXTURE_CUBE_MAP;
+   
+   tex.unpack = 4;
+}
+
+void GLES2Context::TextureState::UpdateSampler(GGLInterface * iface, unsigned tmu)
+{
+   for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
+      if (tmu == sampler2tmu[i])
+         iface->SetSampler(iface, i, tmus[tmu]);
+}
+
+void GLES2Context::UninitializeTextures()
+{
+   for (std::map<GLuint, GGLTexture *>::iterator it = tex.textures.begin(); it != tex.textures.end(); it++) {
+      if (!it->second)
+         continue;
+      free(it->second->levels);
+      free(it->second);
+   }
+}
+
+static inline void GetFormatAndBytesPerPixel(const GLenum format, unsigned * bytesPerPixel,
+      GGLPixelFormat * texFormat)
+{
+   switch (format) {
+   case GL_ALPHA:
+      *texFormat = GGL_PIXEL_FORMAT_A_8;
+      *bytesPerPixel = 1;
+      break;
+   case GL_LUMINANCE:
+      *texFormat = GGL_PIXEL_FORMAT_L_8;
+      *bytesPerPixel = 1;
+      break;
+   case GL_LUMINANCE_ALPHA:
+      *texFormat = GGL_PIXEL_FORMAT_LA_88;
+      *bytesPerPixel = 2;
+      break;
+   case GL_RGB:
+      *texFormat = GGL_PIXEL_FORMAT_RGB_888;
+      *bytesPerPixel = 3;
+      break;
+   case GL_RGBA:
+      *texFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+      *bytesPerPixel = 4;
+      break;
+
+      // internal formats to avoid conversion
+   case GL_UNSIGNED_SHORT_5_6_5:
+      *texFormat = GGL_PIXEL_FORMAT_RGB_565;
+      *bytesPerPixel = 2;
+      break;
+
+   default:
+      assert(0);
+      return;
+   }
+}
+
+static inline void CopyTexture(char * dst, const char * src, const unsigned bytesPerPixel,
+                               const unsigned sx, const unsigned sy,  const unsigned sw,
+                               const unsigned dx, const unsigned dy, const unsigned dw,
+                               const unsigned w, const unsigned h)
+{
+   const unsigned bpp = bytesPerPixel;
+   if (dw == sw && dw == w && sx == 0 && dx == 0)
+      memcpy(dst + dy * dw * bpp, src + sy * sw * bpp, w * h * bpp);
+   else
+      for (unsigned y = 0; y < h; y++)
+         memcpy(dst + ((dy + y) * dw + dx) * bpp, src + ((sy + y) * sw + sx) * bpp, w * bpp); 
+}
+
+void glActiveTexture(GLenum texture)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   unsigned index = texture - GL_TEXTURE0;
+   assert(NELEM(ctx->tex.tmus) > index);
+//   LOGD("agl2: glActiveTexture %u", index);
+   ctx->tex.active = index;
+}
+
+void glBindTexture(GLenum target, GLuint texture)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glBindTexture target=0x%.4X texture=%u active=%u", target, texture, ctx->tex.active);
+   std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(texture);
+   GGLTexture * tex = NULL;
+   if (it != ctx->tex.textures.end()) {
+      tex = it->second;
+      if (!tex) {
+         tex = AllocTexture();
+         tex->type = target;
+         it->second = tex;
+//         LOGD("agl2: glBindTexture allocTexture");
+      }
+//      else
+//         LOGD("agl2: glBindTexture bind existing texture");
+      assert(target == tex->type);
+   } else if (0 == texture) {
+      if (GL_TEXTURE_2D == target)
+      {
+         tex = ctx->tex.tex2D;
+//         LOGD("agl2: glBindTexture bind default tex2D");
+      }
+      else if (GL_TEXTURE_CUBE_MAP == target)
+      {
+         tex = ctx->tex.texCube;
+//         LOGD("agl2: glBindTexture bind default texCube");
+      }
+      else
+         assert(0);
+   } else {
+      if (texture <= ctx->tex.free)
+         ctx->tex.free = texture + 1;
+      tex = AllocTexture();
+      tex->type = target;
+      ctx->tex.textures[texture] = tex;
+//      LOGD("agl2: glBindTexture new texture=%u", texture);
+   }
+   ctx->tex.tmus[ctx->tex.active] = tex;
+//   LOGD("agl2: glBindTexture format=0x%.2X w=%u h=%u levels=%p", tex->format,
+//      tex->width, tex->height, tex->levels);
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data)
+{
+   CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
+}
+
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+   CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+
+void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
+                      GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glCopyTexImage2D target=0x%.4X internalformat=0x%.4X", target, internalformat);
+//   LOGD("x=%d y=%d width=%d height=%d border=%d level=%d ", x, y, width, height, border, level);
+   assert(0 == border);
+   assert(0 == level);
+   unsigned bytesPerPixel = 0;
+   GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
+   GetFormatAndBytesPerPixel(internalformat, &bytesPerPixel, &texFormat);
+
+   assert(texFormat == ctx->rasterizer.frameSurface.format);
+//   LOGD("texFormat=0x%.2X bytesPerPixel=%d \n", texFormat, bytesPerPixel);
+   unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
+
+   assert(ctx->tex.tmus[ctx->tex.active]);
+   assert(y + height <= ctx->rasterizer.frameSurface.height);
+   assert(x + width <= ctx->rasterizer.frameSurface.width);
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+   tex.width = width;
+   tex.height = height;
+   tex.levelCount = 1;
+   tex.format = texFormat;
+   switch (target) {
+   case GL_TEXTURE_2D:
+      tex.levels = realloc(tex.levels, totalSize);
+      CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel,
+                  x, y, ctx->rasterizer.frameSurface.width, 0, 0, width, width, height);
+      break;
+   default:
+      assert(0);
+      return;
+   }
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+
+void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   // x, y are src offset
+   // xoffset and yoffset are dst offset
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glCopyTexSubImage2D target=0x%.4X level=%d", target, level);
+//   LOGD("xoffset=%d yoffset=%d x=%d y=%d width=%d height=%d", xoffset, yoffset, x, y, width, height);
+   assert(0 == level);
+
+   unsigned bytesPerPixel = 4;
+   unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
+
+   assert(ctx->tex.tmus[ctx->tex.active]);
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+
+   assert(tex.format == ctx->rasterizer.frameSurface.format);
+   assert(GGL_PIXEL_FORMAT_RGBA_8888 == tex.format);
+
+   const unsigned srcWidth = ctx->rasterizer.frameSurface.width;
+   const unsigned srcHeight = ctx->rasterizer.frameSurface.height;
+
+   assert(x >= 0 && y >= 0);
+   assert(xoffset >= 0 && yoffset >= 0);
+   assert(x + width <= srcWidth);
+   assert(y + height <= srcHeight);
+   assert(xoffset + width <= tex.width);
+   assert(yoffset + height <= tex.height);
+
+   switch (target) {
+   case GL_TEXTURE_2D:
+      CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel,
+                  x, y, srcWidth, xoffset, yoffset, tex.width, width, height);
+      break;
+   default:
+      assert(0);
+      return;
+   }
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+
+void glDeleteTextures(GLsizei n, const GLuint* textures)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   for (unsigned i = 0; i < n; i++) {
+      std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(textures[i]);
+      if (it == ctx->tex.textures.end())
+         continue;
+      ctx->tex.free = min(ctx->tex.free, textures[i]);
+      for (unsigned i = 0; i <  GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
+         if (ctx->tex.tmus[i] == it->second) {
+            if (GL_TEXTURE_2D == it->second->type)
+               ctx->tex.tmus[i] = ctx->tex.tex2D;
+            else if (GL_TEXTURE_CUBE_MAP == it->second->type)
+               ctx->tex.tmus[i] = ctx->tex.texCube;
+            else
+               assert(0);
+            ctx->tex.UpdateSampler(ctx->iface, i);
+         }
+      if (it->second) {
+         free(it->second->levels);
+         free(it->second);
+      }
+      ctx->tex.textures.erase(it);
+   }
+}
+
+void glGenTextures(GLsizei n, GLuint* textures)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   for (unsigned i = 0; i < n; i++) {
+      textures[i] = 0;
+      for (ctx->tex.free; ctx->tex.free < 0xffffffffu; ctx->tex.free++)
+         if (ctx->tex.textures.find(ctx->tex.free) == ctx->tex.textures.end()) {
+            ctx->tex.textures[ctx->tex.free] = NULL;
+            textures[i] = ctx->tex.free;
+            ctx->tex.free++;
+            break;
+         }
+      assert(textures[i]);
+   }
+}
+
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params)
+{
+   CALL_GL_API(glGetTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetTexParameteriv, target, pname, params);
+}
+
+GLboolean glIsTexture(GLuint texture)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   if (ctx->tex.textures.find(texture) == ctx->tex.textures.end())
+      return GL_FALSE;
+   else
+      return GL_TRUE;
+}
+
+void glPixelStorei(GLenum pname, GLint param)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   assert(GL_UNPACK_ALIGNMENT == pname);
+   assert(1 == param || 2 == param || 4 == param || 8 == param);
+//   LOGD("\n*\n* agl2: glPixelStorei not implemented pname=0x%.4X param=%d \n*", pname, param);
+   ctx->tex.unpack = param;
+//   CALL_GL_API(glPixelStorei, pname, param);
+}
+void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
+                  GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glTexImage2D internalformat=0x%.4X format=0x%.4X type=0x%.4X \n", internalformat, format, type);
+//   LOGD("width=%d height=%d border=%d level=%d pixels=%p \n", width, height, border, level, pixels);
+   switch (type) {
+   case GL_UNSIGNED_BYTE:
+      break;
+   case GL_UNSIGNED_SHORT_5_6_5:
+      internalformat = format = GL_UNSIGNED_SHORT_5_6_5;
+      assert(4 == ctx->tex.unpack);
+      break;
+   default:
+      assert(0);
+   }
+   assert(internalformat == format);
+   assert(0 == border);
+   if (0 != level) {
+      LOGD("agl2: glTexImage2D level=%d", level);
+      return;
+   }
+   unsigned bytesPerPixel = 0;
+   GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
+   GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat);
+
+   assert(texFormat && bytesPerPixel);
+//   LOGD("texFormat=0x%.2X bytesPerPixel=%d active=%u", texFormat, bytesPerPixel, ctx->tex.active);
+   unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
+
+   assert(ctx->tex.tmus[ctx->tex.active]);
+
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+   tex.width = width;
+   tex.height = height;
+   tex.levelCount = 1;
+   tex.format = texFormat;
+
+   switch (target) {
+   case GL_TEXTURE_2D:
+      assert(GL_TEXTURE_2D == ctx->tex.tmus[ctx->tex.active]->type);
+      offset = 0;
+      break;
+      break;
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      assert(GL_TEXTURE_CUBE_MAP == ctx->tex.tmus[ctx->tex.active]->type);
+      assert(width == height);
+      offset = (target - GL_TEXTURE_CUBE_MAP_POSITIVE_X) * size;
+      totalSize = 6 * size;
+      break;
+   default:
+      assert(0);
+      return;
+   }
+
+   tex.levels = realloc(tex.levels, totalSize);
+   if (pixels)
+      CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, 0, 0, width, width, height);
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+
+void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+//   LOGD("agl2: glTexParameterf target=0x%.4X pname=0x%.4X param=%f", target, pname, param);
+   glTexParameteri(target, pname, param);
+}
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params)
+{
+   CALL_GL_API(glTexParameterfv, target, pname, params);
+}
+void glTexParameteri(GLenum target, GLenum pname, GLint param)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("alg2: glTexParameteri target=0x%.0X pname=0x%.4X param=0x%.4X",
+//        target, pname, param);
+   assert(ctx->tex.tmus[ctx->tex.active]);
+   assert(target == ctx->tex.tmus[ctx->tex.active]->type);
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+   switch (pname) {
+   case GL_TEXTURE_WRAP_S:
+   case GL_TEXTURE_WRAP_T:
+      GGLTexture::GGLTextureWrap wrap;
+      switch (param) {
+      case GL_REPEAT:
+         wrap = GGLTexture::GGL_REPEAT;
+         break;
+      case GL_CLAMP_TO_EDGE:
+         wrap = GGLTexture::GGL_CLAMP_TO_EDGE;
+         break;
+      case GL_MIRRORED_REPEAT:
+         wrap = GGLTexture::GGL_MIRRORED_REPEAT;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+      if (GL_TEXTURE_WRAP_S == pname)
+         tex.wrapS = wrap;
+      else
+         tex.wrapT = wrap;
+      break;
+   case GL_TEXTURE_MIN_FILTER:
+      switch (param) {
+      case GL_NEAREST:
+         tex.minFilter = GGLTexture::GGL_NEAREST;
+         break;
+      case GL_LINEAR:
+         tex.minFilter = GGLTexture::GGL_LINEAR;
+         break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+//         tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_NEAREST;
+         break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+//         tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_LINEAR;
+         break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+//         tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_NEAREST;
+         break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+//         tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_LINEAR;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+      break;
+   case GL_TEXTURE_MAG_FILTER:
+      switch (param) {
+      case GL_NEAREST:
+         tex.minFilter = GGLTexture::GGL_NEAREST;
+         break;
+      case GL_LINEAR:
+         tex.minFilter = GGLTexture::GGL_LINEAR;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+      break;
+   default:
+      assert(0);
+      return;
+   }
+   // implementation restriction
+   if (tex.magFilter != tex.minFilter)
+      tex.magFilter = tex.minFilter = GGLTexture::GGL_LINEAR;
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params)
+{
+   CALL_GL_API(glTexParameteriv, target, pname, params);
+}
+void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glTexSubImage2D target=0x%.4X level=%d xoffset=%d yoffset=%d width=%d height=%d format=0x%.4X type=0x%.4X pixels=%p",
+//        target, level, xoffset, yoffset, width, height, format, type, pixels);
+   assert(0 == level);
+   assert(target == ctx->tex.tmus[ctx->tex.active]->type);
+   switch (type) {
+   case GL_UNSIGNED_BYTE:
+      break;
+   case GL_UNSIGNED_SHORT_5_6_5:
+      format = GL_UNSIGNED_SHORT_5_6_5;
+      assert(4 == ctx->tex.unpack);
+      break;
+   default:
+      assert(0);
+   }
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+   GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
+   unsigned bytesPerPixel = 0;
+   GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat);
+   assert(texFormat == tex.format);
+   assert(GL_UNSIGNED_BYTE == type);
+   switch (target) {
+   case GL_TEXTURE_2D:
+      CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, xoffset,
+                  yoffset, tex.width, width, height);
+      break;
+   default:
+      assert(0);
+   }
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
diff --git a/opengl/libagl2/src/vertex.cpp b/opengl/libagl2/src/vertex.cpp
new file mode 100644
index 0000000..021b82b
--- /dev/null
+++ b/opengl/libagl2/src/vertex.cpp
@@ -0,0 +1,373 @@
+#include "gles2context.h"
+
+//#undef LOGD
+//#define LOGD(...)
+
+void GLES2Context::InitializeVertices()
+{
+   vert.vbos = std::map<GLuint, VBO *>(); // the entire struct has been zeroed in constructor
+   vert.free = 1;
+   vert.vbo = NULL;
+   vert.indices = NULL;
+   for (unsigned i = 0; i < GGL_MAXVERTEXATTRIBS; i++)
+      vert.defaultAttribs[i] = Vector4(0,0,0,1);
+}
+
+void GLES2Context::UninitializeVertices()
+{
+   for (std::map<GLuint, VBO *>::iterator it = vert.vbos.begin(); it != vert.vbos.end(); it++) {
+      if (!it->second)
+         continue;
+      free(it->second->data);
+      free(it->second);
+   }
+}
+
+static inline void FetchElement(const GLES2Context * ctx, const unsigned index,
+                                const unsigned maxAttrib, VertexInput * elem)
+{
+   for (unsigned i = 0; i < maxAttrib; i++) {
+      {
+         unsigned size = 0;
+         if (ctx->vert.attribs[i].enabled) {
+            const char * ptr = (const char *)ctx->vert.attribs[i].ptr;
+            ptr += ctx->vert.attribs[i].stride * index;
+            memcpy(elem->attributes + i, ptr, ctx->vert.attribs[i].size * sizeof(float));
+            size = ctx->vert.attribs[i].size;
+//            LOGD("agl2: FetchElement %d attribs size=%d %.2f,%.2f,%.2f,%.2f", i, size, elem->attributes[i].x,
+//                 elem->attributes[i].y, elem->attributes[i].z, elem->attributes[i].w);
+         } else {
+//            LOGD("agl2: FetchElement %d default %.2f,%.2f,%.2f,%.2f", i, ctx->vert.defaultAttribs[i].x,
+//                 ctx->vert.defaultAttribs[i].y, ctx->vert.defaultAttribs[i].z, ctx->vert.defaultAttribs[i].w);
+         }
+
+         switch (size) {
+         case 0: // fall through
+            elem->attributes[i].x = ctx->vert.defaultAttribs[i].x;
+         case 1: // fall through
+            elem->attributes[i].y = ctx->vert.defaultAttribs[i].y;
+         case 2: // fall through
+            elem->attributes[i].z = ctx->vert.defaultAttribs[i].z;
+         case 3: // fall through
+            elem->attributes[i].w = ctx->vert.defaultAttribs[i].w;
+         case 4:
+            break;
+         default:
+            assert(0);
+            break;
+         }
+//         LOGD("agl2: FetchElement %d size=%d %.2f,%.2f,%.2f,%.2f", i, size, elem->attributes[i].x,
+//              elem->attributes[i].y, elem->attributes[i].z, elem->attributes[i].w);
+      }
+   }
+}
+
+template<typename IndexT> static void DrawElementsTriangles(const GLES2Context * ctx,
+      const unsigned count, const IndexT * indices, const unsigned maxAttrib)
+{
+   VertexInput v[3];
+   if (ctx->vert.indices)
+      indices = (IndexT *)((char *)ctx->vert.indices->data + (long)indices);
+   for (unsigned i = 0; i < count; i += 3) {
+      for (unsigned j = 0; j < 3; j++)
+         FetchElement(ctx, indices[i + j], maxAttrib, v + j);
+      ctx->iface->DrawTriangle(ctx->iface, v, v + 1, v + 2);
+   }
+}
+
+static void DrawArraysTriangles(const GLES2Context * ctx, const unsigned first,
+                                const unsigned count, const unsigned maxAttrib)
+{
+//   LOGD("agl: DrawArraysTriangles=%p", DrawArraysTriangles);
+   VertexInput v[3];
+   for (unsigned i = 2; i < count; i+=3) {
+      // TODO: fix order
+      FetchElement(ctx, first + i - 2, maxAttrib, v + 0);
+      FetchElement(ctx, first + i - 1, maxAttrib, v + 1);
+      FetchElement(ctx, first + i - 0, maxAttrib, v + 2);
+      ctx->iface->DrawTriangle(ctx->iface, v + 0, v + 1, v + 2);
+   }
+//   LOGD("agl: DrawArraysTriangles end");
+}
+
+template<typename IndexT> static void DrawElementsTriangleStrip(const GLES2Context * ctx,
+      const unsigned count, const IndexT * indices, const unsigned maxAttrib)
+{
+   VertexInput v[3];
+   if (ctx->vert.indices)
+      indices = (IndexT *)((char *)ctx->vert.indices->data + (long)indices);
+      
+//   LOGD("agl2: DrawElementsTriangleStrip");
+//   for (unsigned i = 0; i < count; i++)
+//      LOGD("indices[%d] = %d", i, indices[i]);
+
+   FetchElement(ctx, indices[0], maxAttrib, v + 0);
+   FetchElement(ctx, indices[1], maxAttrib, v + 1);
+   for (unsigned i = 2; i < count; i ++) {
+      FetchElement(ctx, indices[i], maxAttrib, v + i % 3);
+      ctx->iface->DrawTriangle(ctx->iface, v + (i - 2) % 3, v + (i - 1) % 3 , v + (i + 0) % 3);
+   }
+
+//   for (unsigned i = 2; i < count; i++) {
+//      FetchElement(ctx, indices[i - 2], maxAttrib, v + 0);
+//      FetchElement(ctx, indices[i - 1], maxAttrib, v + 1);
+//      FetchElement(ctx, indices[i - 0], maxAttrib, v + 2);
+//      ctx->iface->DrawTriangle(ctx->iface, v + 0, v + 1, v + 2);
+//   }
+}
+
+static void DrawArraysTriangleStrip(const GLES2Context * ctx, const unsigned first,
+                                    const unsigned count, const unsigned maxAttrib)
+{
+   VertexInput v[3];
+   FetchElement(ctx, first, maxAttrib, v + 0);
+   FetchElement(ctx, first + 1, maxAttrib, v + 1);
+   for (unsigned i = 2; i < count; i++) {
+      // TODO: fix order
+      FetchElement(ctx, first + i, maxAttrib, v + i % 3);
+      ctx->iface->DrawTriangle(ctx->iface, v + (i - 2) % 3, v + (i - 1) % 3 , v + (i + 0) % 3);
+   }
+}
+
+void glBindBuffer(GLenum target, GLuint buffer)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   VBO * vbo = NULL;
+   if (0 != buffer) {
+      std::map<GLuint, VBO *>::iterator it = ctx->vert.vbos.find(buffer);
+      if (it != ctx->vert.vbos.end()) {
+         vbo = it->second;
+         if (!vbo)
+            vbo = (VBO *)calloc(1, sizeof(VBO));
+         it->second = vbo;
+      } else
+         assert(0);
+   }
+   if (GL_ARRAY_BUFFER == target)
+      ctx->vert.vbo = vbo;
+   else if (GL_ELEMENT_ARRAY_BUFFER == target)
+      ctx->vert.indices = vbo;
+   else
+      assert(0);
+   assert(vbo || buffer == 0);
+//   LOGD("\n*\n glBindBuffer 0x%.4X=%d ", target, buffer);
+}
+
+void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   if (GL_ARRAY_BUFFER == target) {
+      assert(ctx->vert.vbo);
+      ctx->vert.vbo->data = realloc(ctx->vert.vbo->data, size);
+      ctx->vert.vbo->size = size;
+      ctx->vert.vbo->usage = usage;
+      if (data)
+         memcpy(ctx->vert.vbo->data, data, size);
+   } else if (GL_ELEMENT_ARRAY_BUFFER == target) {
+      assert(ctx->vert.indices);
+      ctx->vert.indices->data = realloc(ctx->vert.indices->data, size);
+      ctx->vert.indices->size = size;
+      ctx->vert.indices->usage = usage;
+      if (data)
+         memcpy(ctx->vert.indices->data, data, size);
+   } else
+      assert(0);
+//   LOGD("\n*\n glBufferData target=0x%.4X size=%u data=%p usage=0x%.4X \n",
+//        target, size, data, usage);
+}
+
+void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   if (GL_ARRAY_BUFFER == target)
+   {
+      assert(ctx->vert.vbo);
+      assert(0 <= offset);
+      assert(0 <= size);
+      assert(offset + size <= ctx->vert.vbo->size);
+      memcpy((char *)ctx->vert.vbo->data + offset, data, size);
+   }
+   else
+      assert(0);
+}
+
+void glDeleteBuffers(GLsizei n, const GLuint* buffers)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   for (unsigned i = 0; i < n; i++) {
+      std::map<GLuint, VBO*>::iterator it = ctx->vert.vbos.find(buffers[i]);
+      if (it == ctx->vert.vbos.end())
+         continue;
+      ctx->vert.free = min(ctx->vert.free, buffers[i]);
+      if (it->second == ctx->vert.vbo)
+         ctx->vert.vbo = NULL;
+      else if (it->second == ctx->vert.indices)
+         ctx->vert.indices = NULL;
+      if (it->second) {
+         free(it->second->data);
+         free(it->second);
+      }
+   }
+}
+
+void glDisableVertexAttribArray(GLuint index)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   assert(GGL_MAXVERTEXATTRIBS > index);
+   ctx->vert.attribs[index].enabled = false;
+}
+
+void glDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glDrawArrays=%p", glDrawArrays);
+   assert(ctx->rasterizer.CurrentProgram);
+   assert(0 <= first);
+   int maxAttrib = -1;
+   ctx->iface->ShaderProgramGetiv(ctx->rasterizer.CurrentProgram, GL_ACTIVE_ATTRIBUTES, &maxAttrib);
+   assert(0 <= maxAttrib && GGL_MAXVERTEXATTRIBS >= maxAttrib);
+   switch (mode) {
+   case GL_TRIANGLE_STRIP:
+      DrawArraysTriangleStrip(ctx, first, count, maxAttrib);
+      break;
+   case GL_TRIANGLES:
+      DrawArraysTriangles(ctx, first, count, maxAttrib);
+      break;
+   default:
+      LOGE("agl2: glDrawArrays unsupported mode: 0x%.4X \n", mode);
+      assert(0);
+      break;
+   }
+//   LOGD("agl2: glDrawArrays end");
+}
+
+void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glDrawElements=%p mode=0x%.4X count=%d type=0x%.4X indices=%p",
+//        glDrawElements, mode, count, type, indices);
+   if (!ctx->rasterizer.CurrentProgram)
+      return;
+
+   int maxAttrib = -1;
+   ctx->iface->ShaderProgramGetiv(ctx->rasterizer.CurrentProgram, GL_ACTIVE_ATTRIBUTES, &maxAttrib);
+   assert(0 <= maxAttrib && GGL_MAXVERTEXATTRIBS >= maxAttrib);
+//   LOGD("agl2: glDrawElements mode=0x%.4X type=0x%.4X count=%d program=%p indices=%p \n",
+//        mode, type, count, ctx->rasterizer.CurrentProgram, indices);
+   switch (mode) {
+   case GL_TRIANGLES:
+      if (GL_UNSIGNED_SHORT == type)
+         DrawElementsTriangles<unsigned short>(ctx, count, (unsigned short *)indices, maxAttrib);
+      else
+         assert(0);
+      break;
+   case GL_TRIANGLE_STRIP:
+      if (GL_UNSIGNED_SHORT == type)
+         DrawElementsTriangleStrip<unsigned short>(ctx, count, (unsigned short *)indices, maxAttrib);
+      else
+         assert(0);
+      break;
+   default:
+      assert(0);
+   }
+//   LOGD("agl2: glDrawElements end");
+}
+
+void glEnableVertexAttribArray(GLuint index)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->vert.attribs[index].enabled = true;
+//   LOGD("agl2: glEnableVertexAttribArray %d \n", index);
+}
+
+void glGenBuffers(GLsizei n, GLuint* buffers)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   for (unsigned i = 0; i < n; i++) {
+      buffers[i] = 0;
+      for (ctx->vert.free; ctx->vert.free < 0xffffffffu; ctx->vert.free++) {
+         if (ctx->vert.vbos.find(ctx->vert.free) == ctx->vert.vbos.end()) {
+            ctx->vert.vbos[ctx->vert.free] = NULL;
+            buffers[i] = ctx->vert.free;
+//            LOGD("glGenBuffers %d \n", buffers[i]);
+            ctx->vert.free++;
+            break;
+         }
+      }
+      assert(buffers[i]);
+   }
+}
+
+void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized,
+                           GLsizei stride, const GLvoid* ptr)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   assert(GL_FLOAT == type);
+   assert(0 < size && 4 >= size);
+   ctx->vert.attribs[index].size = size;
+   ctx->vert.attribs[index].type = type;
+   ctx->vert.attribs[index].normalized = normalized;
+   if (0 == stride)
+      ctx->vert.attribs[index].stride = size * sizeof(float);
+   else if (stride > 0)
+      ctx->vert.attribs[index].stride = stride;
+   else
+      assert(0);
+//   LOGD("\n*\n*\n* agl2: glVertexAttribPointer program=%u index=%d size=%d stride=%d ptr=%p \n*\n*",
+//        unsigned(ctx->rasterizer.CurrentProgram) ^ 0x04dc18f9, index, size, stride, ptr);
+   if (ctx->vert.vbo)
+      ctx->vert.attribs[index].ptr = (char *)ctx->vert.vbo->data + (long)ptr;
+   else
+      ctx->vert.attribs[index].ptr = ptr;
+//   const float * attrib = (const float *)ctx->vert.attribs[index].ptr;
+//   for (unsigned i = 0; i < 3; i++)
+//      if (3 == size)
+//         LOGD("%.2f %.2f %.2f", attrib[i * 3 + 0], attrib[i * 3 + 1], attrib[i * 3 + 2]);
+//      else if (2 == size)
+//         LOGD("%.2f %.2f", attrib[i * 3 + 0], attrib[i * 3 + 1]);
+   
+}
+
+void glVertexAttrib1f(GLuint indx, GLfloat x)
+{
+   glVertexAttrib4f(indx, x,0,0,1);
+}
+
+void glVertexAttrib1fv(GLuint indx, const GLfloat* values)
+{
+   glVertexAttrib4f(indx, values[0],0,0,1);
+}
+
+void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+   glVertexAttrib4f(indx, x,y,0,1);
+}
+
+void glVertexAttrib2fv(GLuint indx, const GLfloat* values)
+{
+   glVertexAttrib4f(indx, values[0],values[1],0,1);
+}
+
+void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+   glVertexAttrib4f(indx, x,y,z,1);
+}
+
+void glVertexAttrib3fv(GLuint indx, const GLfloat* values)
+{
+   glVertexAttrib4f(indx, values[0],values[1],values[2],1);
+}
+
+void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+   assert(GGL_MAXVERTEXATTRIBS > indx);
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("\n*\n*\n agl2: glVertexAttrib4f %d %.2f,%.2f,%.2f,%.2f \n*\n*", indx, x, y, z, w);
+   ctx->vert.defaultAttribs[indx] = Vector4(x,y,z,w);
+   assert(0);
+}
+
+void glVertexAttrib4fv(GLuint indx, const GLfloat* values)
+{
+   glVertexAttrib4f(indx, values[0], values[1], values[2], values[3]);
+}
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index c8041fc..ff45edc 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -7,17 +7,20 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= 	       \
+	EGL/egl_tls.cpp        \
+	EGL/egl_display.cpp    \
+	EGL/egl_object.cpp     \
 	EGL/egl.cpp 	       \
+	EGL/eglApi.cpp 	       \
 	EGL/trace.cpp              \
 	EGL/getProcAddress.cpp.arm \
-	EGL/hooks.cpp 	       \
 	EGL/Loader.cpp 	       \
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils
+LOCAL_SHARED_LIBRARIES += libcutils libutils libGLESv2_dbg
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libEGL
-
+LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
 # needed on sim build because of weird logging issues
 ifeq ($(TARGET_SIMULATOR),true)
 else
@@ -164,3 +167,6 @@
 LOCAL_MODULE:= libETC1
 
 include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 747c829..e94e50e 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -26,9 +26,9 @@
 
 #include <EGL/egl.h>
 
+#include "egldefs.h"
+#include "glesv2dbg.h"
 #include "hooks.h"
-#include "egl_impl.h"
-
 #include "Loader.h"
 
 // ----------------------------------------------------------------------------
@@ -114,6 +114,7 @@
 
 Loader::~Loader()
 {
+    StopDebugServer();
 }
 
 const char* Loader::getTag(int dpy, int impl)
@@ -177,7 +178,8 @@
         __eglMustCastToProperFunctionPointerType* curr, 
         getProcAddressType getProcAddress) 
 {
-    char scrap[256];
+    const size_t SIZE = 256;
+    char scrap[SIZE];
     while (*api) {
         char const * name = *api;
         __eglMustCastToProperFunctionPointerType f = 
@@ -189,7 +191,7 @@
         if (f == NULL) {
             // Try without the OES postfix
             ssize_t index = ssize_t(strlen(name)) - 3;
-            if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) {
+            if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) {
                 strncpy(scrap, name, index);
                 scrap[index] = 0;
                 f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
@@ -199,10 +201,8 @@
         if (f == NULL) {
             // Try with the OES postfix
             ssize_t index = ssize_t(strlen(name)) - 3;
-            if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) {
-                strncpy(scrap, name, index);
-                scrap[index] = 0;
-                strcat(scrap, "OES");
+            if (index>0 && strcmp(name+index, "OES")) {
+                snprintf(scrap, SIZE, "%sOES", name);
                 f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
                 //LOGD_IF(f, "found <%s> instead", scrap);
             }
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index e13af1c..b11db32 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -17,14 +17,9 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <dlfcn.h>
 
-#include <sys/ioctl.h>
-
-#ifdef HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
+#include <hardware/gralloc.h>
+#include <system/window.h>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
@@ -36,269 +31,42 @@
 #include <cutils/properties.h>
 #include <cutils/memory.h>
 
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
 #include <utils/String8.h>
 
-#include <ui/egl/android_natives.h>
-
-#include "hooks.h"
+#include "egldefs.h"
 #include "egl_impl.h"
+#include "egl_tls.h"
+#include "glesv2dbg.h"
+#include "hooks.h"
 #include "Loader.h"
 
-#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
+#include "egl_display.h"
+#include "egl_object.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-#define VERSION_MAJOR 1
-#define VERSION_MINOR 4
-static char const * const gVendorString     = "Android";
-static char const * const gVersionString    = "1.4 Android META-EGL";
-static char const * const gClientApiString  = "OpenGL ES";
-static char const * const gExtensionString  = 
-        "EGL_KHR_image "
-        "EGL_KHR_image_base "
-        "EGL_KHR_image_pixmap "
-        "EGL_KHR_gl_texture_2D_image "
-        "EGL_KHR_gl_texture_cubemap_image "
-        "EGL_KHR_gl_renderbuffer_image "
-        "EGL_KHR_fence_sync "
-        "EGL_ANDROID_image_native_buffer "
-        "EGL_ANDROID_swap_rectangle "
-        ;
+egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
+gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+gl_hooks_t gHooksNoContext;
+pthread_key_t gGLWrapperKey = -1;
 
 // ----------------------------------------------------------------------------
 
-class egl_object_t {
-    static SortedVector<egl_object_t*> sObjects;
-    static Mutex sLock;
-
-            volatile int32_t  terminated;
-    mutable volatile int32_t  count;
-
-public:
-    egl_object_t() : terminated(0), count(1) { 
-        Mutex::Autolock _l(sLock);
-        sObjects.add(this);
-    }
-
-    inline bool isAlive() const { return !terminated; }
-
-private:
-    bool get() {
-        Mutex::Autolock _l(sLock);
-        if (egl_object_t::sObjects.indexOf(this) >= 0) {
-            android_atomic_inc(&count);
-            return true;
-        }
-        return false;
-    }
-
-    bool put() {
-        Mutex::Autolock _l(sLock);
-        if (android_atomic_dec(&count) == 1) {
-            sObjects.remove(this);
-            return true;
-        }
-        return false;
-    }    
-
-public:
-    template <typename N, typename T>
-    struct LocalRef {
-        N* ref;
-        LocalRef(T o) : ref(0) {
-            N* native = reinterpret_cast<N*>(o);
-            if (o && native->get()) {
-                ref = native;
-            }
-        }
-        ~LocalRef() { 
-            if (ref && ref->put()) {
-                delete ref;
-            }
-        }
-        inline N* get() {
-            return ref;
-        }
-        void acquire() const {
-            if (ref) {
-                android_atomic_inc(&ref->count);
-            }
-        }
-        void release() const {
-            if (ref) {
-                int32_t c = android_atomic_dec(&ref->count);
-                // ref->count cannot be 1 prior atomic_dec because we have
-                // a reference, and if we have one, it means there was
-                // already one before us.
-                LOGE_IF(c==1, "refcount is now 0 in release()");
-            }
-        }
-        void terminate() {
-            if (ref) {
-                ref->terminated = 1;
-                release();
-            }
-        }
-    };
-};
-
-SortedVector<egl_object_t*> egl_object_t::sObjects;
-Mutex egl_object_t::sLock;
-
-
-struct egl_config_t {
-    egl_config_t() {}
-    egl_config_t(int impl, EGLConfig config)
-        : impl(impl), config(config), configId(0), implConfigId(0) { }
-    int         impl;           // the implementation this config is for
-    EGLConfig   config;         // the implementation's EGLConfig
-    EGLint      configId;       // our CONFIG_ID
-    EGLint      implConfigId;   // the implementation's CONFIG_ID
-    inline bool operator < (const egl_config_t& rhs) const {
-        if (impl < rhs.impl) return true;
-        if (impl > rhs.impl) return false;
-        return config < rhs.config;
-    }
-};
-
-struct egl_display_t {
-    enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
-    
-    struct strings_t {
-        char const * vendor;
-        char const * version;
-        char const * clientApi;
-        char const * extensions;
-    };
-
-    struct DisplayImpl {
-        DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
-                        state(NOT_INITIALIZED), numConfigs(0) { }
-        EGLDisplay  dpy;
-        EGLConfig*  config;
-        EGLint      state;
-        EGLint      numConfigs;
-        strings_t   queryString;
-    };
-
-    uint32_t        magic;
-    DisplayImpl     disp[IMPL_NUM_IMPLEMENTATIONS];
-    EGLint          numTotalConfigs;
-    egl_config_t*   configs;
-    uint32_t        refs;
-    Mutex           lock;
-    
-    egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0) { }
-    ~egl_display_t() { magic = 0; }
-    inline bool isValid() const { return magic == '_dpy'; }
-    inline bool isAlive() const { return isValid(); }
-};
-
-struct egl_surface_t : public egl_object_t
-{
-    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
-
-    egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
-            EGLSurface surface, int impl, egl_connection_t const* cnx)
-    : dpy(dpy), surface(surface), config(config), win(win), impl(impl), cnx(cnx) {
-    }
-    ~egl_surface_t() {
-    }
-    EGLDisplay                  dpy;
-    EGLSurface                  surface;
-    EGLConfig                   config;
-    sp<ANativeWindow>           win;
-    int                         impl;
-    egl_connection_t const*     cnx;
-};
-
-struct egl_context_t : public egl_object_t
-{
-    typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
-    
-    egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
-            int impl, egl_connection_t const* cnx, int version) 
-    : dpy(dpy), context(context), config(config), read(0), draw(0), impl(impl),
-      cnx(cnx), version(version)
-    {
-    }
-    EGLDisplay                  dpy;
-    EGLContext                  context;
-    EGLConfig                   config;
-    EGLSurface                  read;
-    EGLSurface                  draw;
-    int                         impl;
-    egl_connection_t const*     cnx;
-    int                         version;
-};
-
-struct egl_image_t : public egl_object_t
-{
-    typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
-
-    egl_image_t(EGLDisplay dpy, EGLContext context)
-        : dpy(dpy), context(context)
-    {
-        memset(images, 0, sizeof(images));
-    }
-    EGLDisplay dpy;
-    EGLContext context;
-    EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
-};
-
-struct egl_sync_t : public egl_object_t
-{
-    typedef egl_object_t::LocalRef<egl_sync_t, EGLSyncKHR> Ref;
-
-    egl_sync_t(EGLDisplay dpy, EGLContext context, EGLSyncKHR sync)
-        : dpy(dpy), context(context), sync(sync)
-    {
-    }
-    EGLDisplay dpy;
-    EGLContext context;
-    EGLSyncKHR sync;
-};
-
-typedef egl_surface_t::Ref  SurfaceRef;
-typedef egl_context_t::Ref  ContextRef;
-typedef egl_image_t::Ref    ImageRef;
-typedef egl_sync_t::Ref     SyncRef;
-
-struct tls_t
-{
-    tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
-    EGLint      error;
-    EGLContext  ctx;
-    EGLBoolean  logCallWithNoContext;
-};
-
-
-// ----------------------------------------------------------------------------
-
-static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
-static egl_display_t gDisplay[NUM_DISPLAYS];
-static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_key_t gEGLThreadLocalStorageKey = -1;
-
-// ----------------------------------------------------------------------------
-
-EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
-EGLAPI gl_hooks_t gHooksNoContext;
-EGLAPI pthread_key_t gGLWrapperKey = -1;
-
 #if EGL_TRACE
 
 EGLAPI pthread_key_t gGLTraceKey = -1;
 
 // ----------------------------------------------------------------------------
 
-static int gEGLTraceLevel;
-static int gEGLApplicationTraceLevel;
-extern EGLAPI gl_hooks_t gHooksTrace;
+int gEGLDebugLevel;
+
+static int sEGLTraceLevel;
+static int sEGLApplicationTraceLevel;
+
+extern gl_hooks_t gHooksTrace;
+extern gl_hooks_t gHooksDebug;
 
 static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
     pthread_setspecific(gGLTraceKey, value);
@@ -308,18 +76,49 @@
     return static_cast<gl_hooks_t*>(pthread_getspecific(gGLTraceKey));
 }
 
-static void initEglTraceLevel() {
+void initEglTraceLevel() {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.egl.trace", value, "0");
     int propertyLevel = atoi(value);
-    int applicationLevel = gEGLApplicationTraceLevel;
-    gEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
+    int applicationLevel = sEGLApplicationTraceLevel;
+    sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
+
+    property_get("debug.egl.debug_proc", value, "");
+    long pid = getpid();
+    char procPath[128] = {};
+    sprintf(procPath, "/proc/%ld/cmdline", pid);
+    FILE * file = fopen(procPath, "r");
+    if (file)
+    {
+        char cmdline[256] = {};
+        if (fgets(cmdline, sizeof(cmdline) - 1, file))
+        {
+            if (!strcmp(value, cmdline))
+                sEGLTraceLevel = 1;
+        }
+        fclose(file);
+    }
+
+    if (sEGLTraceLevel > 0)
+    {
+        property_get("debug.egl.debug_port", value, "5039");
+        const unsigned short port = (unsigned short)atoi(value);
+        property_get("debug.egl.debug_forceUseFile", value, "0");
+        const bool forceUseFile = (bool)atoi(value);
+        property_get("debug.egl.debug_maxFileSize", value, "8");
+        const unsigned int maxFileSize = atoi(value) << 20;
+        property_get("debug.egl.debug_filePath", value, "/data/local/tmp/dump.gles2dbg");
+        StartDebugServer(port, forceUseFile, maxFileSize, value);
+    }
 }
 
-static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
-    if (gEGLTraceLevel > 0) {
+void setGLHooksThreadSpecific(gl_hooks_t const *value) {
+    if (sEGLTraceLevel > 0) {
         setGlTraceThreadSpecific(value);
         setGlThreadSpecific(&gHooksTrace);
+    } else if (sEGLTraceLevel > 0 && value != &gHooksNoContext) {
+        setGlTraceThreadSpecific(value);
+        setGlThreadSpecific(&gHooksDebug);
     } else {
         setGlThreadSpecific(value);
     }
@@ -331,186 +130,21 @@
  */
 extern "C"
 void setGLTraceLevel(int level) {
-    gEGLApplicationTraceLevel = level;
+    sEGLApplicationTraceLevel = level;
 }
 
 #else
 
-static inline void setGLHooksThreadSpecific(gl_hooks_t const *value) {
+void setGLHooksThreadSpecific(gl_hooks_t const *value) {
     setGlThreadSpecific(value);
 }
 
 #endif
 
-// ----------------------------------------------------------------------------
-
-static __attribute__((noinline))
-const char *egl_strerror(EGLint err)
-{
-    switch (err){
-        case EGL_SUCCESS:               return "EGL_SUCCESS";
-        case EGL_NOT_INITIALIZED:       return "EGL_NOT_INITIALIZED";
-        case EGL_BAD_ACCESS:            return "EGL_BAD_ACCESS";
-        case EGL_BAD_ALLOC:             return "EGL_BAD_ALLOC";
-        case EGL_BAD_ATTRIBUTE:         return "EGL_BAD_ATTRIBUTE";
-        case EGL_BAD_CONFIG:            return "EGL_BAD_CONFIG";
-        case EGL_BAD_CONTEXT:           return "EGL_BAD_CONTEXT";
-        case EGL_BAD_CURRENT_SURFACE:   return "EGL_BAD_CURRENT_SURFACE";
-        case EGL_BAD_DISPLAY:           return "EGL_BAD_DISPLAY";
-        case EGL_BAD_MATCH:             return "EGL_BAD_MATCH";
-        case EGL_BAD_NATIVE_PIXMAP:     return "EGL_BAD_NATIVE_PIXMAP";
-        case EGL_BAD_NATIVE_WINDOW:     return "EGL_BAD_NATIVE_WINDOW";
-        case EGL_BAD_PARAMETER:         return "EGL_BAD_PARAMETER";
-        case EGL_BAD_SURFACE:           return "EGL_BAD_SURFACE";
-        case EGL_CONTEXT_LOST:          return "EGL_CONTEXT_LOST";
-        default: return "UNKNOWN";
-    }
-}
-
-static __attribute__((noinline))
-void clearTLS() {
-    if (gEGLThreadLocalStorageKey != -1) {
-        tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
-        if (tls) {
-            delete tls;
-            pthread_setspecific(gEGLThreadLocalStorageKey, 0);
-        }
-    }
-}
-
-static tls_t* getTLS()
-{
-    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
-    if (tls == 0) {
-        tls = new tls_t;
-        pthread_setspecific(gEGLThreadLocalStorageKey, tls);
-    }
-    return tls;
-}
-
-static inline void clearError() {
-    // This must clear the error from all the underlying EGL implementations as
-    // well as the EGL wrapper layer.
-    eglGetError();
-}
-
-template<typename T>
-static __attribute__((noinline))
-T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) {
-    if (gEGLThreadLocalStorageKey == -1) {
-        pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
-        if (gEGLThreadLocalStorageKey == -1)
-            pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
-        pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
-    }
-    tls_t* tls = getTLS();
-    if (tls->error != error) {
-        LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
-        tls->error = error;
-    }
-    return returnValue;
-}
-
-static __attribute__((noinline))
-GLint getError() {
-    if (gEGLThreadLocalStorageKey == -1)
-        return EGL_SUCCESS;
-    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
-    if (!tls) return EGL_SUCCESS;
-    GLint error = tls->error;
-    tls->error = EGL_SUCCESS;
-    return error;
-}
-
-static __attribute__((noinline))
-void setContext(EGLContext ctx) {
-    if (gEGLThreadLocalStorageKey == -1) {
-        pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
-        if (gEGLThreadLocalStorageKey == -1)
-            pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
-        pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
-    }
-    tls_t* tls = getTLS();
-    tls->ctx = ctx;
-}
-
-static __attribute__((noinline))
-EGLContext getContext() {
-    if (gEGLThreadLocalStorageKey == -1)
-        return EGL_NO_CONTEXT;
-    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
-    if (!tls) return EGL_NO_CONTEXT;
-    return tls->ctx;
-}
-
 /*****************************************************************************/
 
-template<typename T>
-static __attribute__((noinline))
-int binarySearch(
-        T const sortedArray[], int first, int last, T key)
-{
-    while (first <= last) {
-        int mid = (first + last) / 2;
-        if (sortedArray[mid] < key) {
-            first = mid + 1;
-        } else if (key < sortedArray[mid]) { 
-            last = mid - 1;
-        } else {
-            return mid;
-        }
-    }
-    return -1;
-}
-
-static int cmp_configs(const void* a, const void *b)
-{
-    const egl_config_t& c0 = *(egl_config_t const *)a;
-    const egl_config_t& c1 = *(egl_config_t const *)b;
-    return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
-}
-
-struct extention_map_t {
-    const char* name;
-    __eglMustCastToProperFunctionPointerType address;
-};
-
-static const extention_map_t gExtentionMap[] = {
-    { "eglLockSurfaceKHR",  
-            (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 
-    { "eglUnlockSurfaceKHR", 
-            (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 
-    { "eglCreateImageKHR",  
-            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 
-    { "eglDestroyImageKHR", 
-            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 
-    { "eglSetSwapRectangleANDROID", 
-            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, 
-};
-
-extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
-
-// accesses protected by gInitDriverMutex
-static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> gGLExtentionMap;
-static int gGLExtentionSlot = 0;
-
-static void(*findProcAddress(const char* name,
-        const extention_map_t* map, size_t n))() 
-{
-    for (uint32_t i=0 ; i<n ; i++) {
-        if (!strcmp(name, map[i].name)) {
-            return map[i].address;
-        }
-    }
-    return NULL;
-}
-
-// ----------------------------------------------------------------------------
-
 static int gl_no_context() {
-    tls_t* tls = getTLS();
-    if (tls->logCallWithNoContext == EGL_TRUE) {
-        tls->logCallWithNoContext = EGL_FALSE;
+    if (egl_tls_t::logNoContextCall()) {
         LOGE("call to OpenGL ES API with no current context "
              "(logged once per thread)");
     }
@@ -538,45 +172,23 @@
 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
 static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
 
+// ----------------------------------------------------------------------------
 
-static inline
-egl_display_t* get_display(EGLDisplay dpy)
-{
-    uintptr_t index = uintptr_t(dpy)-1U;
-    return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
+egl_display_t* validate_display(EGLDisplay dpy) {
+    egl_display_t * const dp = get_display(dpy);
+    if (!dp)
+        return setError(EGL_BAD_DISPLAY, (egl_display_t*)NULL);
+    if (!dp->isReady())
+        return setError(EGL_NOT_INITIALIZED, (egl_display_t*)NULL);
+
+    return dp;
 }
 
-template<typename NATIVE, typename EGL>
-static inline NATIVE* egl_to_native_cast(EGL arg) {
-    return reinterpret_cast<NATIVE*>(arg);
-}
-
-static inline
-egl_surface_t* get_surface(EGLSurface surface) {   
-    return egl_to_native_cast<egl_surface_t>(surface);
-}
-
-static inline
-egl_context_t* get_context(EGLContext context) {
-    return egl_to_native_cast<egl_context_t>(context);
-}
-
-static inline
-egl_image_t* get_image(EGLImageKHR image) {
-    return egl_to_native_cast<egl_image_t>(image);
-}
-
-static inline
-egl_sync_t* get_sync(EGLSyncKHR sync) {
-    return egl_to_native_cast<egl_sync_t>(sync);
-}
-
-static egl_connection_t* validate_display_config(
-        EGLDisplay dpy, EGLConfig config,
-        egl_display_t const*& dp)
-{
-    dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
+egl_connection_t* validate_display_config(EGLDisplay dpy, EGLConfig config,
+        egl_display_t const*& dp) {
+    dp = validate_display(dpy);
+    if (!dp)
+        return (egl_connection_t*) NULL;
 
     if (intptr_t(config) >= dp->numTotalConfigs) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
@@ -588,41 +200,26 @@
     return cnx;
 }
 
-static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx)
-{
-    if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_display(dpy)->isAlive())
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_context(ctx)->isAlive())
-        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    return EGL_TRUE;
-}
-
-static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
-{
-    if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_display(dpy)->isAlive())
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_surface(surface)->isAlive())
-        return setError(EGL_BAD_SURFACE, EGL_FALSE);
-    return EGL_TRUE;
-}
+// ----------------------------------------------------------------------------
 
 EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
 {
     ImageRef _i(image);
-    if (!_i.get()) return EGL_NO_IMAGE_KHR;
-    
-    EGLContext context = getContext();
+    if (!_i.get())
+        return EGL_NO_IMAGE_KHR;
+
+    EGLContext context = egl_tls_t::getContext();
     if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
         return EGL_NO_IMAGE_KHR;
-    
+
     egl_context_t const * const c = get_context(context);
-    if (!c->isAlive())
+    if (c == NULL) // this should never happen
         return EGL_NO_IMAGE_KHR;
 
+    // here we don't validate the context because if it's been marked for
+    // termination, this call should still succeed since it's internal to
+    // EGL.
+
     egl_image_t const * const i = get_image(image);
     return i->images[c->impl];
 }
@@ -633,10 +230,7 @@
 //    d->disp[]
 //    egl_init_drivers_locked()
 //
-static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
-
-EGLBoolean egl_init_drivers_locked()
-{
+static EGLBoolean egl_init_drivers_locked() {
     if (sEarlyInitState) {
         // initialized by static ctor. should be set here.
         return EGL_FALSE;
@@ -644,28 +238,15 @@
 
     // get our driver loader
     Loader& loader(Loader::getInstance());
-    
-    // dynamically load all our EGL implementations for all displays
-    // and retrieve the corresponding EGLDisplay
-    // if that fails, don't use this driver.
-    // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
+
+    // dynamically load all our EGL implementations
     egl_connection_t* cnx;
-    egl_display_t* d = &gDisplay[0];
 
     cnx = &gEGLImpl[IMPL_SOFTWARE];
     if (cnx->dso == 0) {
         cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
         cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
         cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
-        if (cnx->dso) {
-            EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-            LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
-            d->disp[IMPL_SOFTWARE].dpy = dpy; 
-            if (dpy == EGL_NO_DISPLAY) {
-                loader.close(cnx->dso);
-                cnx->dso = NULL;
-            }
-        }
     }
 
     cnx = &gEGLImpl[IMPL_HARDWARE];
@@ -676,15 +257,6 @@
             cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
             cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
             cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
-            if (cnx->dso) {
-                EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-                LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
-                d->disp[IMPL_HARDWARE].dpy = dpy; 
-                if (dpy == EGL_NO_DISPLAY) {
-                    loader.close(cnx->dso);
-                    cnx->dso = NULL;
-                }
-            }
         } else {
             LOGD("3D hardware acceleration is disabled");
         }
@@ -697,1474 +269,82 @@
     return EGL_TRUE;
 }
 
-EGLBoolean egl_init_drivers()
-{
+static pthread_mutex_t sInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
+
+EGLBoolean egl_init_drivers() {
     EGLBoolean res;
-    pthread_mutex_lock(&gInitDriverMutex);
+    pthread_mutex_lock(&sInitDriverMutex);
     res = egl_init_drivers_locked();
-    pthread_mutex_unlock(&gInitDriverMutex);
+    pthread_mutex_unlock(&sInitDriverMutex);
     return res;
 }
 
+void gl_unimplemented() {
+    LOGE("called unimplemented OpenGL ES API");
+}
+
+// ----------------------------------------------------------------------------
+
+#if USE_FAST_TLS_KEY
+
+// We have a dedicated TLS slot in bionic
+static inline gl_hooks_t const * volatile * get_tls_hooks() {
+    volatile void *tls_base = __get_tls();
+    gl_hooks_t const * volatile * tls_hooks =
+            reinterpret_cast<gl_hooks_t const * volatile *>(tls_base);
+    return tls_hooks;
+}
+
+void setGlThreadSpecific(gl_hooks_t const *value) {
+    gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
+    tls_hooks[TLS_SLOT_OPENGL_API] = value;
+}
+
+gl_hooks_t const* getGlThreadSpecific() {
+    gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
+    gl_hooks_t const* hooks = tls_hooks[TLS_SLOT_OPENGL_API];
+    if (hooks) return hooks;
+    return &gHooksNoContext;
+}
+
+#else
+
+void setGlThreadSpecific(gl_hooks_t const *value) {
+    pthread_setspecific(gGLWrapperKey, value);
+}
+
+gl_hooks_t const* getGlThreadSpecific() {
+    gl_hooks_t const* hooks =  static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey));
+    if (hooks) return hooks;
+    return &gHooksNoContext;
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+// GL / EGL hooks
+// ----------------------------------------------------------------------------
+
+#undef GL_ENTRY
+#undef EGL_ENTRY
+#define GL_ENTRY(_r, _api, ...) #_api,
+#define EGL_ENTRY(_r, _api, ...) #_api,
+
+char const * const gl_names[] = {
+    #include "entries.in"
+    NULL
+};
+
+char const * const egl_names[] = {
+    #include "egl_entries.in"
+    NULL
+};
+
+#undef GL_ENTRY
+#undef EGL_ENTRY
+
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
 
-using namespace android;
-
-EGLDisplay eglGetDisplay(NativeDisplayType display)
-{
-    clearError();
-
-    uint32_t index = uint32_t(display);
-    if (index >= NUM_DISPLAYS) {
-        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
-    }
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
-    }
-    
-    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
-    return dpy;
-}
-
-// ----------------------------------------------------------------------------
-// Initialization
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
-{
-    clearError();
-
-    egl_display_t * const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    Mutex::Autolock _l(dp->lock);
-
-    if (dp->refs > 0) {
-        if (major != NULL) *major = VERSION_MAJOR;
-        if (minor != NULL) *minor = VERSION_MINOR;
-        dp->refs++;
-        return EGL_TRUE;
-    }
-
-#if EGL_TRACE
-
-    // Called both at early_init time and at this time. (Early_init is pre-zygote, so
-    // the information from that call may be stale.)
-    initEglTraceLevel();
-
-#endif
-
-    setGLHooksThreadSpecific(&gHooksNoContext);
-
-    // initialize each EGL and
-    // build our own extension string first, based on the extension we know
-    // and the extension supported by our client implementation
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        cnx->major = -1;
-        cnx->minor = -1;
-        if (!cnx->dso) 
-            continue;
-
-#if defined(ADRENO130)
-#warning "Adreno-130 eglInitialize() workaround"
-        /*
-         * The ADRENO 130 driver returns a different EGLDisplay each time
-         * eglGetDisplay() is called, but also makes the EGLDisplay invalid
-         * after eglTerminate() has been called, so that eglInitialize() 
-         * cannot be called again. Therefore, we need to make sure to call
-         * eglGetDisplay() before calling eglInitialize();
-         */
-        if (i == IMPL_HARDWARE) {
-            dp->disp[i].dpy =
-                cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        }
-#endif
-
-
-        EGLDisplay idpy = dp->disp[i].dpy;
-        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
-            //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
-            //        i, idpy, cnx->major, cnx->minor, cnx);
-
-            // display is now initialized
-            dp->disp[i].state = egl_display_t::INITIALIZED;
-
-            // get the query-strings for this display for each implementation
-            dp->disp[i].queryString.vendor =
-                cnx->egl.eglQueryString(idpy, EGL_VENDOR);
-            dp->disp[i].queryString.version =
-                cnx->egl.eglQueryString(idpy, EGL_VERSION);
-            dp->disp[i].queryString.extensions =
-                    cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
-            dp->disp[i].queryString.clientApi =
-                cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
-
-        } else {
-            LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
-                    egl_strerror(cnx->egl.eglGetError()));
-        }
-    }
-
-    EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
-            EGLint n;
-            if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
-                dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
-                if (dp->disp[i].config) {
-                    if (cnx->egl.eglGetConfigs(
-                            dp->disp[i].dpy, dp->disp[i].config, n,
-                            &dp->disp[i].numConfigs))
-                    {
-                        dp->numTotalConfigs += n;
-                        res = EGL_TRUE;
-                    }
-                }
-            }
-        }
-    }
-
-    if (res == EGL_TRUE) {
-        dp->configs = new egl_config_t[ dp->numTotalConfigs ];
-        for (int i=0, k=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-            egl_connection_t* const cnx = &gEGLImpl[i];
-            if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
-                for (int j=0 ; j<dp->disp[i].numConfigs ; j++) {
-                    dp->configs[k].impl = i;
-                    dp->configs[k].config = dp->disp[i].config[j];
-                    dp->configs[k].configId = k + 1; // CONFIG_ID start at 1
-                    // store the implementation's CONFIG_ID
-                    cnx->egl.eglGetConfigAttrib(
-                            dp->disp[i].dpy,
-                            dp->disp[i].config[j],
-                            EGL_CONFIG_ID,
-                            &dp->configs[k].implConfigId);
-                    k++;
-                }
-            }
-        }
-
-        // sort our configurations so we can do binary-searches
-        qsort(  dp->configs,
-                dp->numTotalConfigs,
-                sizeof(egl_config_t), cmp_configs);
-
-        dp->refs++;
-        if (major != NULL) *major = VERSION_MAJOR;
-        if (minor != NULL) *minor = VERSION_MINOR;
-        return EGL_TRUE;
-    }
-    return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
-}
-
-EGLBoolean eglTerminate(EGLDisplay dpy)
-{
-    // NOTE: don't unload the drivers b/c some APIs can be called
-    // after eglTerminate() has been called. eglTerminate() only
-    // terminates an EGLDisplay, not a EGL itself.
-
-    clearError();
-
-    egl_display_t* const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    Mutex::Autolock _l(dp->lock);
-
-    if (dp->refs == 0) {
-        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
-    }
-
-    // this is specific to Android, display termination is ref-counted.
-    if (dp->refs > 1) {
-        dp->refs--;
-        return EGL_TRUE;
-    }
-
-    EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
-            if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
-                LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
-                        egl_strerror(cnx->egl.eglGetError()));
-            }
-            // REVISIT: it's unclear what to do if eglTerminate() fails
-            free(dp->disp[i].config);
-
-            dp->disp[i].numConfigs = 0;
-            dp->disp[i].config = 0;
-            dp->disp[i].state = egl_display_t::TERMINATED;
-
-            res = EGL_TRUE;
-        }
-    }
-    
-    // TODO: all egl_object_t should be marked for termination
-    
-    dp->refs--;
-    dp->numTotalConfigs = 0;
-    delete [] dp->configs;
-
-    return res;
-}
-
-// ----------------------------------------------------------------------------
-// configuration
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglGetConfigs(   EGLDisplay dpy,
-                            EGLConfig *configs,
-                            EGLint config_size, EGLint *num_config)
-{
-    clearError();
-
-    egl_display_t const * const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    GLint numConfigs = dp->numTotalConfigs;
-    if (!configs) {
-        *num_config = numConfigs;
-        return EGL_TRUE;
-    }
-
-    GLint n = 0;
-    for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
-        *configs++ = EGLConfig(i);
-        config_size--;
-        n++;
-    }
-    
-    *num_config = n;
-    return EGL_TRUE;
-}
-
-EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
-                            EGLConfig *configs, EGLint config_size,
-                            EGLint *num_config)
-{
-    clearError();
-
-    egl_display_t const * const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    if (num_config==0) {
-        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    }
-
-    EGLint n;
-    EGLBoolean res = EGL_FALSE;
-    *num_config = 0;
-
-    
-    // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 
-    // to do this, we have to go through the attrib_list array once
-    // to figure out both its size and if it contains an EGL_CONFIG_ID
-    // key. If so, the full array is copied and patched.
-    // NOTE: we assume that there can be only one occurrence
-    // of EGL_CONFIG_ID.
-    
-    EGLint patch_index = -1;
-    GLint attr;
-    size_t size = 0;
-    if (attrib_list) {
-        while ((attr=attrib_list[size]) != EGL_NONE) {
-            if (attr == EGL_CONFIG_ID)
-                patch_index = size;
-            size += 2;
-        }
-    }
-    if (patch_index >= 0) {
-        size += 2; // we need copy the sentinel as well
-        EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
-        if (new_list == 0)
-            return setError(EGL_BAD_ALLOC, EGL_FALSE);
-        memcpy(new_list, attrib_list, size*sizeof(EGLint));
-
-        // patch the requested EGL_CONFIG_ID
-        bool found = false;
-        EGLConfig ourConfig(0);
-        EGLint& configId(new_list[patch_index+1]);
-        for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
-            if (dp->configs[i].configId == configId) {
-                ourConfig = EGLConfig(i);
-                configId = dp->configs[i].implConfigId;
-                found = true;
-                break;
-            }
-        }
-
-        egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
-        if (found && cnx->dso) {
-            // and switch to the new list
-            attrib_list = const_cast<const EGLint *>(new_list);
-
-            // At this point, the only configuration that can match is
-            // dp->configs[i][index], however, we don't know if it would be
-            // rejected because of the other attributes, so we do have to call
-            // cnx->egl.eglChooseConfig() -- but we don't have to loop
-            // through all the EGLimpl[].
-            // We also know we can only get a single config back, and we know
-            // which one.
-
-            res = cnx->egl.eglChooseConfig(
-                    dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
-                    attrib_list, configs, config_size, &n);
-            if (res && n>0) {
-                // n has to be 0 or 1, by construction, and we already know
-                // which config it will return (since there can be only one).
-                if (configs) {
-                    configs[0] = ourConfig;
-                }
-                *num_config = 1;
-            }
-        }
-
-        free(const_cast<EGLint *>(attrib_list));
-        return res;
-    }
-
-
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglChooseConfig(
-                    dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
-                if (configs) {
-                    // now we need to convert these client EGLConfig to our
-                    // internal EGLConfig format.
-                    // This is done in O(n Log(n)) time.
-                    for (int j=0 ; j<n ; j++) {
-                        egl_config_t key(i, configs[j]);
-                        intptr_t index = binarySearch<egl_config_t>(
-                                dp->configs, 0, dp->numTotalConfigs, key);
-                        if (index >= 0) {
-                            configs[j] = EGLConfig(index);
-                        } else {
-                            return setError(EGL_BAD_CONFIG, EGL_FALSE);
-                        }
-                    }
-                    configs += n;
-                    config_size -= n;
-                }
-                *num_config += n;
-                res = EGL_TRUE;
-            }
-        }
-    }
-    return res;
-}
-
-EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
-        EGLint attribute, EGLint *value)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (!cnx) return EGL_FALSE;
-    
-    if (attribute == EGL_CONFIG_ID) {
-        *value = dp->configs[intptr_t(config)].configId;
-        return EGL_TRUE;
-    }
-    return cnx->egl.eglGetConfigAttrib(
-            dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-            dp->configs[intptr_t(config)].config, attribute, value);
-}
-
-// ----------------------------------------------------------------------------
-// surfaces
-// ----------------------------------------------------------------------------
-
-EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
-                                    NativeWindowType window,
-                                    const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (cnx) {
-        EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
-        EGLConfig iConfig = dp->configs[intptr_t(config)].config;
-        EGLint format;
-
-        // for now fail if the window is not a Surface.
-        int type = -1;
-        ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
-        if ((anw->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &type) != 0) ||
-                (type == NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT)) {
-            LOGE("native window is a SurfaceTextureClient (currently "
-                    "unsupported)");
-            return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
-        }
-
-        // set the native window's buffers format to match this config
-        if (cnx->egl.eglGetConfigAttrib(iDpy,
-                iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
-            if (format != 0) {
-                native_window_set_buffers_geometry(window, 0, 0, format);
-            }
-        }
-
-        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
-                iDpy, iConfig, window, attrib_list);
-        if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
-                    dp->configs[intptr_t(config)].impl, cnx);
-            return s;
-        }
-    }
-    return EGL_NO_SURFACE;
-}
-
-EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
-                                    NativePixmapType pixmap,
-                                    const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (cnx) {
-        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                dp->configs[intptr_t(config)].config, pixmap, attrib_list);
-        if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
-                    dp->configs[intptr_t(config)].impl, cnx);
-            return s;
-        }
-    }
-    return EGL_NO_SURFACE;
-}
-
-EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
-                                    const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (cnx) {
-        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                dp->configs[intptr_t(config)].config, attrib_list);
-        if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
-                    dp->configs[intptr_t(config)].impl, cnx);
-            return s;
-        }
-    }
-    return EGL_NO_SURFACE;
-}
-                                    
-EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
-{
-    clearError();
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_display_t const * const dp = get_display(dpy);
-
-    egl_surface_t * const s = get_surface(surface);
-    EGLBoolean result = s->cnx->egl.eglDestroySurface(
-            dp->disp[s->impl].dpy, s->surface);
-    if (result == EGL_TRUE) {
-        if (s->win != NULL) {
-            native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
-        }
-        _s.terminate();
-    }
-    return result;
-}
-
-EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
-                            EGLint attribute, EGLint *value)
-{
-    clearError();
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
-
-    EGLBoolean result(EGL_TRUE);
-    if (attribute == EGL_CONFIG_ID) {
-        // We need to remap EGL_CONFIG_IDs
-        *value = dp->configs[intptr_t(s->config)].configId;
-    } else {
-        result = s->cnx->egl.eglQuerySurface(
-                dp->disp[s->impl].dpy, s->surface, attribute, value);
-    }
-
-    return result;
-}
-
-// ----------------------------------------------------------------------------
-// Contexts
-// ----------------------------------------------------------------------------
-
-EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
-                            EGLContext share_list, const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (cnx) {
-        if (share_list != EGL_NO_CONTEXT) {
-            egl_context_t* const c = get_context(share_list);
-            share_list = c->context;
-        }
-        EGLContext context = cnx->egl.eglCreateContext(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                dp->configs[intptr_t(config)].config,
-                share_list, attrib_list);
-        if (context != EGL_NO_CONTEXT) {
-            // figure out if it's a GLESv1 or GLESv2
-            int version = 0;
-            if (attrib_list) {
-                while (*attrib_list != EGL_NONE) {
-                    GLint attr = *attrib_list++;
-                    GLint value = *attrib_list++;
-                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
-                        if (value == 1) {
-                            version = GLESv1_INDEX;
-                        } else if (value == 2) {
-                            version = GLESv2_INDEX;
-                        }
-                    }
-                };
-            }
-            egl_context_t* c = new egl_context_t(dpy, context, config,
-                    dp->configs[intptr_t(config)].impl, cnx, version);
-            return c;
-        }
-    }
-    return EGL_NO_CONTEXT;
-}
-
-EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
-{
-    clearError();
-
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;
-    egl_display_t const * const dp = get_display(dpy);
-    egl_context_t * const c = get_context(ctx);
-    EGLBoolean result = c->cnx->egl.eglDestroyContext(
-            dp->disp[c->impl].dpy, c->context);
-    if (result == EGL_TRUE) {
-        _c.terminate();
-    }
-    return result;
-}
-
-static void loseCurrent(egl_context_t * cur_c)
-{
-    if (cur_c) {
-        egl_surface_t * cur_r = get_surface(cur_c->read);
-        egl_surface_t * cur_d = get_surface(cur_c->draw);
-
-        // by construction, these are either 0 or valid (possibly terminated)
-        // it should be impossible for these to be invalid
-        ContextRef _cur_c(cur_c);
-        SurfaceRef _cur_r(cur_r);
-        SurfaceRef _cur_d(cur_d);
-
-        cur_c->read = NULL;
-        cur_c->draw = NULL;
-
-        _cur_c.release();
-        _cur_r.release();
-        _cur_d.release();
-    }
-}
-
-EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
-                            EGLSurface read, EGLContext ctx)
-{
-    clearError();
-
-    // get a reference to the object passed in
-    ContextRef _c(ctx);
-    SurfaceRef _d(draw);
-    SurfaceRef _r(read);
-
-    // validate the display and the context (if not EGL_NO_CONTEXT)
-    egl_display_t const * const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
-        // EGL_NO_CONTEXT is valid
-        return EGL_FALSE;
-    }
-
-    // these are the underlying implementation's object
-    EGLContext impl_ctx  = EGL_NO_CONTEXT;
-    EGLSurface impl_draw = EGL_NO_SURFACE;
-    EGLSurface impl_read = EGL_NO_SURFACE;
-
-    // these are our objects structs passed in
-    egl_context_t       * c = NULL;
-    egl_surface_t const * d = NULL;
-    egl_surface_t const * r = NULL;
-
-    // these are the current objects structs
-    egl_context_t * cur_c = get_context(getContext());
-    
-    if (ctx != EGL_NO_CONTEXT) {
-        c = get_context(ctx);
-        impl_ctx = c->context;
-    } else {
-        // no context given, use the implementation of the current context
-        if (cur_c == NULL) {
-            // no current context
-            if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
-                // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
-                return setError(EGL_BAD_MATCH, EGL_FALSE);
-            }
-            // not an error, there is just no current context.
-            return EGL_TRUE;
-        }
-    }
-
-    // retrieve the underlying implementation's draw EGLSurface
-    if (draw != EGL_NO_SURFACE) {
-        d = get_surface(draw);
-        // make sure the EGLContext and EGLSurface passed in are for
-        // the same driver
-        if (c && d->impl != c->impl)
-            return setError(EGL_BAD_MATCH, EGL_FALSE);
-        impl_draw = d->surface;
-    }
-
-    // retrieve the underlying implementation's read EGLSurface
-    if (read != EGL_NO_SURFACE) {
-        r = get_surface(read);
-        // make sure the EGLContext and EGLSurface passed in are for
-        // the same driver
-        if (c && r->impl != c->impl)
-            return setError(EGL_BAD_MATCH, EGL_FALSE);
-        impl_read = r->surface;
-    }
-
-    EGLBoolean result;
-
-    if (c) {
-        result = c->cnx->egl.eglMakeCurrent(
-                dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
-    } else {
-        result = cur_c->cnx->egl.eglMakeCurrent(
-                dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
-    }
-
-    if (result == EGL_TRUE) {
-
-        loseCurrent(cur_c);
-
-        if (ctx != EGL_NO_CONTEXT) {
-            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
-            setContext(ctx);
-            _c.acquire();
-            _r.acquire();
-            _d.acquire();
-            c->read = read;
-            c->draw = draw;
-        } else {
-            setGLHooksThreadSpecific(&gHooksNoContext);
-            setContext(EGL_NO_CONTEXT);
-        }
-    }
-    return result;
-}
-
-
-EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
-                            EGLint attribute, EGLint *value)
-{
-    clearError();
-
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;    
-    
-    egl_display_t const * const dp = get_display(dpy);
-    egl_context_t * const c = get_context(ctx);
-
-    EGLBoolean result(EGL_TRUE);
-    if (attribute == EGL_CONFIG_ID) {
-        *value = dp->configs[intptr_t(c->config)].configId;
-    } else {
-        // We need to remap EGL_CONFIG_IDs
-        result = c->cnx->egl.eglQueryContext(
-                dp->disp[c->impl].dpy, c->context, attribute, value);
-    }
-
-    return result;
-}
-
-EGLContext eglGetCurrentContext(void)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would correctly return EGL_NO_CONTEXT.
-
-    clearError();
-
-    EGLContext ctx = getContext();
-    return ctx;
-}
-
-EGLSurface eglGetCurrentSurface(EGLint readdraw)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would correctly return EGL_NO_SURFACE.
-
-    clearError();
-
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
-        switch (readdraw) {
-            case EGL_READ: return c->read;
-            case EGL_DRAW: return c->draw;            
-            default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
-        }
-    }
-    return EGL_NO_SURFACE;
-}
-
-EGLDisplay eglGetCurrentDisplay(void)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would correctly return EGL_NO_DISPLAY.
-
-    clearError();
-
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
-        return c->dpy;
-    }
-    return EGL_NO_DISPLAY;
-}
-
-EGLBoolean eglWaitGL(void)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would return GL_TRUE, which isn't wrong.
-
-    clearError();
-
-    EGLBoolean res = EGL_TRUE;
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (uint32_t(c->impl)>=2)
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        egl_connection_t* const cnx = &gEGLImpl[c->impl];
-        if (!cnx->dso) 
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->egl.eglWaitGL();
-    }
-    return res;
-}
-
-EGLBoolean eglWaitNative(EGLint engine)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would return GL_TRUE, which isn't wrong.
-
-    clearError();
-
-    EGLBoolean res = EGL_TRUE;
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (uint32_t(c->impl)>=2)
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        egl_connection_t* const cnx = &gEGLImpl[c->impl];
-        if (!cnx->dso) 
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->egl.eglWaitNative(engine);
-    }
-    return res;
-}
-
-EGLint eglGetError(void)
-{
-    EGLint result = EGL_SUCCESS;
-    EGLint err;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        err = EGL_SUCCESS;
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso)
-            err = cnx->egl.eglGetError();
-        if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
-            result = err;
-    }
-    err = getError();
-    if (result == EGL_SUCCESS)
-        result = err;
-    return result;
-}
-
-// Note: Similar implementations of these functions also exist in
-// gl2.cpp and gl.cpp, and are used by applications that call the
-// exported entry points directly.
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
-
-static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
-static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
-
-static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
-{
-    GLeglImageOES implImage =
-        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
-    glEGLImageTargetTexture2DOES_impl(target, implImage);
-}
-
-static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
-{
-    GLeglImageOES implImage =
-        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
-    glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
-}
-
-__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
-{
-    // eglGetProcAddress() could be the very first function called
-    // in which case we must make sure we've initialized ourselves, this
-    // happens the first time egl_get_display() is called.
-
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        setError(EGL_BAD_PARAMETER, NULL);
-        return  NULL;
-    }
-
-    __eglMustCastToProperFunctionPointerType addr;
-    addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
-    if (addr) return addr;
-
-    // this protects accesses to gGLExtentionMap and gGLExtentionSlot
-    pthread_mutex_lock(&gInitDriverMutex);
-
-        /*
-         * Since eglGetProcAddress() is not associated to anything, it needs
-         * to return a function pointer that "works" regardless of what
-         * the current context is.
-         *
-         * For this reason, we return a "forwarder", a small stub that takes
-         * care of calling the function associated with the context
-         * currently bound.
-         *
-         * We first look for extensions we've already resolved, if we're seeing
-         * this extension for the first time, we go through all our
-         * implementations and call eglGetProcAddress() and record the
-         * result in the appropriate implementation hooks and return the
-         * address of the forwarder corresponding to that hook set.
-         *
-         */
-
-        const String8 name(procname);
-        addr = gGLExtentionMap.valueFor(name);
-        const int slot = gGLExtentionSlot;
-
-        LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
-                "no more slots for eglGetProcAddress(\"%s\")",
-                procname);
-
-        if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
-            bool found = false;
-            for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-                egl_connection_t* const cnx = &gEGLImpl[i];
-                if (cnx->dso && cnx->egl.eglGetProcAddress) {
-                    found = true;
-                    // Extensions are independent of the bound context
-                    cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
-                    cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
-#if EGL_TRACE
-                    gHooksTrace.ext.extensions[slot] =
-#endif
-                            cnx->egl.eglGetProcAddress(procname);
-                }
-            }
-            if (found) {
-                addr = gExtensionForwarders[slot];
-
-                if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
-                    glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
-                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
-                }
-                if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
-                    glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
-                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
-                }
-
-                gGLExtentionMap.add(name, addr);
-                gGLExtentionSlot++;
-            }
-        }
-
-    pthread_mutex_unlock(&gInitDriverMutex);
-    return addr;
-}
-
-EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
-{
-    clearError();
-
-    SurfaceRef _s(draw);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, draw))
-        return EGL_FALSE;    
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(draw);
-    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
-}
-
-EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
-                            NativePixmapType target)
-{
-    clearError();
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
-    return s->cnx->egl.eglCopyBuffers(
-            dp->disp[s->impl].dpy, s->surface, target);
-}
-
-const char* eglQueryString(EGLDisplay dpy, EGLint name)
-{
-    clearError();
-
-    egl_display_t const * const dp = get_display(dpy);
-    switch (name) {
-        case EGL_VENDOR:
-            return gVendorString;
-        case EGL_VERSION:
-            return gVersionString;
-        case EGL_EXTENSIONS:
-            return gExtensionString;
-        case EGL_CLIENT_APIS:
-            return gClientApiString;
-    }
-    return setError(EGL_BAD_PARAMETER, (const char *)0);
-}
-
-
-// ----------------------------------------------------------------------------
-// EGL 1.1
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglSurfaceAttrib(
-        EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
-{
-    clearError();
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->egl.eglSurfaceAttrib) {
-        return s->cnx->egl.eglSurfaceAttrib(
-                dp->disp[s->impl].dpy, s->surface, attribute, value);
-    }
-    return setError(EGL_BAD_SURFACE, EGL_FALSE);
-}
-
-EGLBoolean eglBindTexImage(
-        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
-{
-    clearError();
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->egl.eglBindTexImage) {
-        return s->cnx->egl.eglBindTexImage(
-                dp->disp[s->impl].dpy, s->surface, buffer);
-    }
-    return setError(EGL_BAD_SURFACE, EGL_FALSE);
-}
-
-EGLBoolean eglReleaseTexImage(
-        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
-{
-    clearError();
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->egl.eglReleaseTexImage) {
-        return s->cnx->egl.eglReleaseTexImage(
-                dp->disp[s->impl].dpy, s->surface, buffer);
-    }
-    return setError(EGL_BAD_SURFACE, EGL_FALSE);
-}
-
-EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
-{
-    clearError();
-
-    egl_display_t * const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglSwapInterval) {
-                if (cnx->egl.eglSwapInterval(
-                        dp->disp[i].dpy, interval) == EGL_FALSE) {
-                    res = EGL_FALSE;
-                }
-            }
-        }
-    }
-    return res;
-}
-
-
-// ----------------------------------------------------------------------------
-// EGL 1.2
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglWaitClient(void)
-{
-    clearError();
-
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would return GL_TRUE, which isn't wrong.
-    EGLBoolean res = EGL_TRUE;
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (uint32_t(c->impl)>=2)
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        egl_connection_t* const cnx = &gEGLImpl[c->impl];
-        if (!cnx->dso) 
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (cnx->egl.eglWaitClient) {
-            res = cnx->egl.eglWaitClient();
-        } else {
-            res = cnx->egl.eglWaitGL();
-        }
-    }
-    return res;
-}
-
-EGLBoolean eglBindAPI(EGLenum api)
-{
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    }
-
-    // bind this API on all EGLs
-    EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglBindAPI) {
-                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
-                    res = EGL_FALSE;
-                }
-            }
-        }
-    }
-    return res;
-}
-
-EGLenum eglQueryAPI(void)
-{
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    }
-
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglQueryAPI) {
-                // the first one we find is okay, because they all
-                // should be the same
-                return cnx->egl.eglQueryAPI();
-            }
-        }
-    }
-    // or, it can only be OpenGL ES
-    return EGL_OPENGL_ES_API;
-}
-
-EGLBoolean eglReleaseThread(void)
-{
-    clearError();
-
-    // If there is context bound to the thread, release it
-    loseCurrent(get_context(getContext()));
-
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglReleaseThread) {
-                cnx->egl.eglReleaseThread();
-            }
-        }
-    }
-    clearTLS();    
-    return EGL_TRUE;
-}
-
-EGLSurface eglCreatePbufferFromClientBuffer(
-          EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
-          EGLConfig config, const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (!cnx) return EGL_FALSE;
-    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
-        return cnx->egl.eglCreatePbufferFromClientBuffer(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                buftype, buffer,
-                dp->configs[intptr_t(config)].config, attrib_list);
-    }
-    return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
-}
-
-// ----------------------------------------------------------------------------
-// EGL_EGLEXT_VERSION 3
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
-        const EGLint *attrib_list)
-{
-    clearError();
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;
-
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
-
-    if (s->cnx->egl.eglLockSurfaceKHR) {
-        return s->cnx->egl.eglLockSurfaceKHR(
-                dp->disp[s->impl].dpy, s->surface, attrib_list);
-    }
-    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-}
-
-EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
-{
-    clearError();
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;
-
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
-
-    if (s->cnx->egl.eglUnlockSurfaceKHR) {
-        return s->cnx->egl.eglUnlockSurfaceKHR(
-                dp->disp[s->impl].dpy, s->surface);
-    }
-    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-}
-
-EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
-        EGLClientBuffer buffer, const EGLint *attrib_list)
-{
-    clearError();
-
-    if (ctx != EGL_NO_CONTEXT) {
-        ContextRef _c(ctx);
-        if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
-        if (!validate_display_context(dpy, ctx))
-            return EGL_NO_IMAGE_KHR;
-        egl_display_t const * const dp = get_display(dpy);
-        egl_context_t * const c = get_context(ctx);
-        // since we have an EGLContext, we know which implementation to use
-        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
-                dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
-        if (image == EGL_NO_IMAGE_KHR)
-            return image;
-            
-        egl_image_t* result = new egl_image_t(dpy, ctx);
-        result->images[c->impl] = image;
-        return (EGLImageKHR)result;
-    } else {
-        // EGL_NO_CONTEXT is a valid parameter
-        egl_display_t const * const dp = get_display(dpy);
-        if (dp == 0) {
-            return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
-        }
-
-        /* Since we don't have a way to know which implementation to call,
-         * we're calling all of them. If at least one of the implementation
-         * succeeded, this is a success.
-         */
-
-        EGLint currentError = eglGetError();
-
-        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
-        bool success = false;
-        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-            egl_connection_t* const cnx = &gEGLImpl[i];
-            implImages[i] = EGL_NO_IMAGE_KHR;
-            if (cnx->dso) {
-                if (cnx->egl.eglCreateImageKHR) {
-                    implImages[i] = cnx->egl.eglCreateImageKHR(
-                            dp->disp[i].dpy, ctx, target, buffer, attrib_list);
-                    if (implImages[i] != EGL_NO_IMAGE_KHR) {
-                        success = true;
-                    }
-                }
-            }
-        }
-
-        if (!success) {
-            // failure, if there was an error when we entered this function,
-            // the error flag must not be updated.
-            // Otherwise, the error is whatever happened in the implementation
-            // that faulted.
-            if (currentError != EGL_SUCCESS) {
-                setError(currentError, EGL_NO_IMAGE_KHR);
-            }
-            return EGL_NO_IMAGE_KHR;
-        } else {
-            // In case of success, we need to clear all error flags
-            // (especially those caused by the implementation that didn't
-            // succeed). TODO: we could avoid this if we knew this was
-            // a "full" success (all implementation succeeded).
-            eglGetError();
-        }
-
-        egl_image_t* result = new egl_image_t(dpy, ctx);
-        memcpy(result->images, implImages, sizeof(implImages));
-        return (EGLImageKHR)result;
-    }
-}
-
-EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
-{
-    clearError();
-
-    egl_display_t const * const dp = get_display(dpy);
-     if (dp == 0) {
-         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-     }
-
-     ImageRef _i(img);
-     if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-
-     egl_image_t* image = get_image(img);
-     bool success = false;
-     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-         egl_connection_t* const cnx = &gEGLImpl[i];
-         if (image->images[i] != EGL_NO_IMAGE_KHR) {
-             if (cnx->dso) {
-                 if (cnx->egl.eglDestroyImageKHR) {
-                     if (cnx->egl.eglDestroyImageKHR(
-                             dp->disp[i].dpy, image->images[i])) {
-                         success = true;
-                     }
-                 }
-             }
-         }
-     }
-     if (!success)
-         return EGL_FALSE;
-
-     _i.terminate();
-
-     return EGL_TRUE;
-}
-
-// ----------------------------------------------------------------------------
-// EGL_EGLEXT_VERSION 5
-// ----------------------------------------------------------------------------
-
-
-EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
-{
-    clearError();
-
-    EGLContext ctx = eglGetCurrentContext();
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
-    if (!validate_display_context(dpy, ctx))
-        return EGL_NO_SYNC_KHR;
-    egl_display_t const * const dp = get_display(dpy);
-    egl_context_t * const c = get_context(ctx);
-    EGLSyncKHR result = EGL_NO_SYNC_KHR;
-    if (c->cnx->egl.eglCreateSyncKHR) {
-        EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
-                dp->disp[c->impl].dpy, type, attrib_list);
-        if (sync == EGL_NO_SYNC_KHR)
-            return sync;
-        result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
-    }
-    return (EGLSyncKHR)result;
-}
-
-EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
-{
-    clearError();
-
-    egl_display_t const * const dp = get_display(dpy);
-    if (dp == 0) {
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    }
-
-    SyncRef _s(sync);
-    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    egl_sync_t* syncObject = get_sync(sync);
-
-    EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;
-
-    EGLBoolean result = EGL_FALSE;
-    egl_context_t * const c = get_context(ctx);
-    if (c->cnx->egl.eglDestroySyncKHR) {
-        result = c->cnx->egl.eglDestroySyncKHR(
-                dp->disp[c->impl].dpy, syncObject->sync);
-        if (result)
-            _s.terminate();
-    }
-    return result;
-}
-
-EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
-{
-    clearError();
-
-    egl_display_t const * const dp = get_display(dpy);
-    if (dp == 0) {
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    }
-
-    SyncRef _s(sync);
-    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    egl_sync_t* syncObject = get_sync(sync);
-
-    EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;
-
-    egl_context_t * const c = get_context(ctx);
-
-    if (c->cnx->egl.eglClientWaitSyncKHR) {
-        return c->cnx->egl.eglClientWaitSyncKHR(
-                dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
-    }
-
-    return EGL_FALSE;
-}
-
-EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
-{
-    clearError();
-
-    egl_display_t const * const dp = get_display(dpy);
-    if (dp == 0) {
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    }
-
-    SyncRef _s(sync);
-    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    egl_sync_t* syncObject = get_sync(sync);
-
-    EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;
-
-    egl_context_t * const c = get_context(ctx);
-
-    if (c->cnx->egl.eglGetSyncAttribKHR) {
-        return c->cnx->egl.eglGetSyncAttribKHR(
-                dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
-    }
-
-    return EGL_FALSE;
-}
-
-// ----------------------------------------------------------------------------
-// ANDROID extensions
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
-        EGLint left, EGLint top, EGLint width, EGLint height)
-{
-    clearError();
-
-    SurfaceRef _s(draw);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, draw))
-        return EGL_FALSE;    
-    egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(draw);
-    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
-        return s->cnx->egl.eglSetSwapRectangleANDROID(
-                dp->disp[s->impl].dpy, s->surface, left, top, width, height);
-    }
-    return setError(EGL_BAD_DISPLAY, NULL);
-}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
new file mode 100644
index 0000000..7d5d010
--- /dev/null
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -0,0 +1,1440 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <hardware/gralloc.h>
+#include <system/window.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <cutils/memory.h>
+
+#include <utils/KeyedVector.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+
+#include "egl_impl.h"
+#include "egl_tls.h"
+#include "glesv2dbg.h"
+#include "hooks.h"
+
+#include "egl_display.h"
+#include "egl_impl.h"
+#include "egl_object.h"
+#include "egl_tls.h"
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+
+static char const * const sVendorString     = "Android";
+static char const * const sVersionString    = "1.4 Android META-EGL";
+static char const * const sClientApiString  = "OpenGL ES";
+static char const * const sExtensionString  =
+        "EGL_KHR_image "
+        "EGL_KHR_image_base "
+        "EGL_KHR_image_pixmap "
+        "EGL_KHR_gl_texture_2D_image "
+        "EGL_KHR_gl_texture_cubemap_image "
+        "EGL_KHR_gl_renderbuffer_image "
+        "EGL_KHR_fence_sync "
+        "EGL_ANDROID_image_native_buffer "
+        "EGL_ANDROID_swap_rectangle "
+        ;
+
+struct extention_map_t {
+    const char* name;
+    __eglMustCastToProperFunctionPointerType address;
+};
+
+static const extention_map_t sExtentionMap[] = {
+    { "eglLockSurfaceKHR",
+            (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
+    { "eglUnlockSurfaceKHR",
+            (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
+    { "eglCreateImageKHR",
+            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
+    { "eglDestroyImageKHR",
+            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
+    { "eglSetSwapRectangleANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
+};
+
+// accesses protected by sExtensionMapMutex
+static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
+static int sGLExtentionSlot = 0;
+static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void(*findProcAddress(const char* name,
+        const extention_map_t* map, size_t n))() {
+    for (uint32_t i=0 ; i<n ; i++) {
+        if (!strcmp(name, map[i].name)) {
+            return map[i].address;
+        }
+    }
+    return NULL;
+}
+
+// ----------------------------------------------------------------------------
+
+template<typename T>
+static __attribute__((noinline))
+int binarySearch(T const sortedArray[], int first, int last, T key) {
+    while (first <= last) {
+        int mid = (first + last) / 2;
+        if (sortedArray[mid] < key) {
+            first = mid + 1;
+        } else if (key < sortedArray[mid]) {
+            last = mid - 1;
+        } else {
+            return mid;
+        }
+    }
+    return -1;
+}
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
+extern EGLBoolean egl_init_drivers();
+extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
+extern int gEGLDebugLevel;
+extern gl_hooks_t gHooksTrace;
+extern gl_hooks_t gHooksDebug;
+} // namespace android;
+
+// ----------------------------------------------------------------------------
+
+static inline void clearError() { egl_tls_t::clearError(); }
+static inline EGLContext getContext() { return egl_tls_t::getContext(); }
+
+// ----------------------------------------------------------------------------
+
+EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
+{
+    clearError();
+
+    uint32_t index = uint32_t(display);
+    if (index >= NUM_DISPLAYS) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+
+    EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
+    return dpy;
+}
+
+// ----------------------------------------------------------------------------
+// Initialization
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+    clearError();
+
+    egl_display_t * const dp = get_display(dpy);
+    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    EGLBoolean res = dp->initialize(major, minor);
+
+    return res;
+}
+
+EGLBoolean eglTerminate(EGLDisplay dpy)
+{
+    // NOTE: don't unload the drivers b/c some APIs can be called
+    // after eglTerminate() has been called. eglTerminate() only
+    // terminates an EGLDisplay, not a EGL itself.
+
+    clearError();
+
+    egl_display_t* const dp = get_display(dpy);
+    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    EGLBoolean res = dp->terminate();
+    
+    return res;
+}
+
+// ----------------------------------------------------------------------------
+// configuration
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglGetConfigs(   EGLDisplay dpy,
+                            EGLConfig *configs,
+                            EGLint config_size, EGLint *num_config)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    GLint numConfigs = dp->numTotalConfigs;
+    if (!configs) {
+        *num_config = numConfigs;
+        return EGL_TRUE;
+    }
+
+    GLint n = 0;
+    for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
+        *configs++ = EGLConfig(i);
+        config_size--;
+        n++;
+    }
+    
+    *num_config = n;
+    return EGL_TRUE;
+}
+
+EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
+                            EGLConfig *configs, EGLint config_size,
+                            EGLint *num_config)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    if (num_config==0) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    EGLint n;
+    EGLBoolean res = EGL_FALSE;
+    *num_config = 0;
+
+    
+    // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 
+    // to do this, we have to go through the attrib_list array once
+    // to figure out both its size and if it contains an EGL_CONFIG_ID
+    // key. If so, the full array is copied and patched.
+    // NOTE: we assume that there can be only one occurrence
+    // of EGL_CONFIG_ID.
+    
+    EGLint patch_index = -1;
+    GLint attr;
+    size_t size = 0;
+    if (attrib_list) {
+        while ((attr=attrib_list[size]) != EGL_NONE) {
+            if (attr == EGL_CONFIG_ID)
+                patch_index = size;
+            size += 2;
+        }
+    }
+    if (patch_index >= 0) {
+        size += 2; // we need copy the sentinel as well
+        EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
+        if (new_list == 0)
+            return setError(EGL_BAD_ALLOC, EGL_FALSE);
+        memcpy(new_list, attrib_list, size*sizeof(EGLint));
+
+        // patch the requested EGL_CONFIG_ID
+        bool found = false;
+        EGLConfig ourConfig(0);
+        EGLint& configId(new_list[patch_index+1]);
+        for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
+            if (dp->configs[i].configId == configId) {
+                ourConfig = EGLConfig(i);
+                configId = dp->configs[i].implConfigId;
+                found = true;
+                break;
+            }
+        }
+
+        egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
+        if (found && cnx->dso) {
+            // and switch to the new list
+            attrib_list = const_cast<const EGLint *>(new_list);
+
+            // At this point, the only configuration that can match is
+            // dp->configs[i][index], however, we don't know if it would be
+            // rejected because of the other attributes, so we do have to call
+            // cnx->egl.eglChooseConfig() -- but we don't have to loop
+            // through all the EGLimpl[].
+            // We also know we can only get a single config back, and we know
+            // which one.
+
+            res = cnx->egl.eglChooseConfig(
+                    dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
+                    attrib_list, configs, config_size, &n);
+            if (res && n>0) {
+                // n has to be 0 or 1, by construction, and we already know
+                // which config it will return (since there can be only one).
+                if (configs) {
+                    configs[0] = ourConfig;
+                }
+                *num_config = 1;
+            }
+        }
+
+        free(const_cast<EGLint *>(attrib_list));
+        return res;
+    }
+
+
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglChooseConfig(
+                    dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
+                if (configs) {
+                    // now we need to convert these client EGLConfig to our
+                    // internal EGLConfig format.
+                    // This is done in O(n Log(n)) time.
+                    for (int j=0 ; j<n ; j++) {
+                        egl_config_t key(i, configs[j]);
+                        intptr_t index = binarySearch<egl_config_t>(
+                                dp->configs, 0, dp->numTotalConfigs, key);
+                        if (index >= 0) {
+                            configs[j] = EGLConfig(index);
+                        } else {
+                            return setError(EGL_BAD_CONFIG, EGL_FALSE);
+                        }
+                    }
+                    configs += n;
+                    config_size -= n;
+                }
+                *num_config += n;
+                res = EGL_TRUE;
+            }
+        }
+    }
+    return res;
+}
+
+EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+        EGLint attribute, EGLint *value)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (!cnx) return EGL_FALSE;
+    
+    if (attribute == EGL_CONFIG_ID) {
+        *value = dp->configs[intptr_t(config)].configId;
+        return EGL_TRUE;
+    }
+    return cnx->egl.eglGetConfigAttrib(
+            dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+            dp->configs[intptr_t(config)].config, attribute, value);
+}
+
+// ----------------------------------------------------------------------------
+// surfaces
+// ----------------------------------------------------------------------------
+
+EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
+                                    NativeWindowType window,
+                                    const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (cnx) {
+        EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
+        EGLConfig iConfig = dp->configs[intptr_t(config)].config;
+        EGLint format;
+
+        // set the native window's buffers format to match this config
+        if (cnx->egl.eglGetConfigAttrib(iDpy,
+                iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
+            if (format != 0) {
+                native_window_set_buffers_geometry(window, 0, 0, format);
+            }
+        }
+
+        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
+                iDpy, iConfig, window, attrib_list);
+        if (surface != EGL_NO_SURFACE) {
+            egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
+                    dp->configs[intptr_t(config)].impl, cnx);
+            return s;
+        }
+    }
+    return EGL_NO_SURFACE;
+}
+
+EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
+                                    NativePixmapType pixmap,
+                                    const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (cnx) {
+        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
+                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+                dp->configs[intptr_t(config)].config, pixmap, attrib_list);
+        if (surface != EGL_NO_SURFACE) {
+            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
+                    dp->configs[intptr_t(config)].impl, cnx);
+            return s;
+        }
+    }
+    return EGL_NO_SURFACE;
+}
+
+EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
+                                    const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (cnx) {
+        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
+                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+                dp->configs[intptr_t(config)].config, attrib_list);
+        if (surface != EGL_NO_SURFACE) {
+            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
+                    dp->configs[intptr_t(config)].impl, cnx);
+            return s;
+        }
+    }
+    return EGL_NO_SURFACE;
+}
+                                    
+EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t * const s = get_surface(surface);
+    EGLBoolean result = s->cnx->egl.eglDestroySurface(
+            dp->disp[s->impl].dpy, s->surface);
+    if (result == EGL_TRUE) {
+        if (s->win != NULL) {
+            native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
+        }
+        _s.terminate();
+    }
+    return result;
+}
+
+EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
+                            EGLint attribute, EGLint *value)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    EGLBoolean result(EGL_TRUE);
+    if (attribute == EGL_CONFIG_ID) {
+        // We need to remap EGL_CONFIG_IDs
+        *value = dp->configs[intptr_t(s->config)].configId;
+    } else {
+        result = s->cnx->egl.eglQuerySurface(
+                dp->disp[s->impl].dpy, s->surface, attribute, value);
+    }
+
+    return result;
+}
+
+// ----------------------------------------------------------------------------
+// Contexts
+// ----------------------------------------------------------------------------
+
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
+                            EGLContext share_list, const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (cnx) {
+        if (share_list != EGL_NO_CONTEXT) {
+            egl_context_t* const c = get_context(share_list);
+            share_list = c->context;
+        }
+        EGLContext context = cnx->egl.eglCreateContext(
+                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+                dp->configs[intptr_t(config)].config,
+                share_list, attrib_list);
+        if (context != EGL_NO_CONTEXT) {
+            // figure out if it's a GLESv1 or GLESv2
+            int version = 0;
+            if (attrib_list) {
+                while (*attrib_list != EGL_NONE) {
+                    GLint attr = *attrib_list++;
+                    GLint value = *attrib_list++;
+                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
+                        if (value == 1) {
+                            version = GLESv1_INDEX;
+                        } else if (value == 2) {
+                            version = GLESv2_INDEX;
+                        }
+                    }
+                };
+            }
+            egl_context_t* c = new egl_context_t(dpy, context, config,
+                    dp->configs[intptr_t(config)].impl, cnx, version);
+            return c;
+        }
+    }
+    return EGL_NO_CONTEXT;
+}
+
+EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp)
+        return EGL_FALSE;
+
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+    
+    egl_context_t * const c = get_context(ctx);
+    EGLBoolean result = c->cnx->egl.eglDestroyContext(
+            dp->disp[c->impl].dpy, c->context);
+    if (result == EGL_TRUE) {
+        _c.terminate();
+    }
+    return result;
+}
+
+static void loseCurrent(egl_context_t * cur_c)
+{
+    if (cur_c) {
+        egl_surface_t * cur_r = get_surface(cur_c->read);
+        egl_surface_t * cur_d = get_surface(cur_c->draw);
+
+        // by construction, these are either 0 or valid (possibly terminated)
+        // it should be impossible for these to be invalid
+        ContextRef _cur_c(cur_c);
+        SurfaceRef _cur_r(cur_r);
+        SurfaceRef _cur_d(cur_d);
+
+        cur_c->read = NULL;
+        cur_c->draw = NULL;
+
+        _cur_c.release();
+        _cur_r.release();
+        _cur_d.release();
+    }
+}
+
+EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
+                            EGLSurface read, EGLContext ctx)
+{
+    clearError();
+
+    egl_display_t const * const dp = get_display(dpy);
+    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
+    // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
+    // a valid but uninitialized display.
+    if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
+         (draw != EGL_NO_SURFACE) ) {
+        if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+    }
+
+    // get a reference to the object passed in
+    ContextRef _c(ctx);
+    SurfaceRef _d(draw);
+    SurfaceRef _r(read);
+
+    // validate the context (if not EGL_NO_CONTEXT)
+    if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
+        // EGL_NO_CONTEXT is valid
+        return EGL_FALSE;
+    }
+
+    // these are the underlying implementation's object
+    EGLContext impl_ctx  = EGL_NO_CONTEXT;
+    EGLSurface impl_draw = EGL_NO_SURFACE;
+    EGLSurface impl_read = EGL_NO_SURFACE;
+
+    // these are our objects structs passed in
+    egl_context_t       * c = NULL;
+    egl_surface_t const * d = NULL;
+    egl_surface_t const * r = NULL;
+
+    // these are the current objects structs
+    egl_context_t * cur_c = get_context(getContext());
+    
+    if (ctx != EGL_NO_CONTEXT) {
+        c = get_context(ctx);
+        impl_ctx = c->context;
+    } else {
+        // no context given, use the implementation of the current context
+        if (cur_c == NULL) {
+            // no current context
+            if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
+                // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
+                return setError(EGL_BAD_MATCH, EGL_FALSE);
+            }
+            // not an error, there is just no current context.
+            return EGL_TRUE;
+        }
+    }
+
+    // retrieve the underlying implementation's draw EGLSurface
+    if (draw != EGL_NO_SURFACE) {
+        d = get_surface(draw);
+        // make sure the EGLContext and EGLSurface passed in are for
+        // the same driver
+        if (c && d->impl != c->impl)
+            return setError(EGL_BAD_MATCH, EGL_FALSE);
+        impl_draw = d->surface;
+    }
+
+    // retrieve the underlying implementation's read EGLSurface
+    if (read != EGL_NO_SURFACE) {
+        r = get_surface(read);
+        // make sure the EGLContext and EGLSurface passed in are for
+        // the same driver
+        if (c && r->impl != c->impl)
+            return setError(EGL_BAD_MATCH, EGL_FALSE);
+        impl_read = r->surface;
+    }
+
+    EGLBoolean result;
+
+    if (c) {
+        result = c->cnx->egl.eglMakeCurrent(
+                dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+    } else {
+        result = cur_c->cnx->egl.eglMakeCurrent(
+                dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+    }
+
+    if (result == EGL_TRUE) {
+
+        loseCurrent(cur_c);
+
+        if (ctx != EGL_NO_CONTEXT) {
+            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
+            egl_tls_t::setContext(ctx);
+            if (gEGLDebugLevel > 0) {
+                CreateDbgContext(c->version, c->cnx->hooks[c->version]);
+            }
+            _c.acquire();
+            _r.acquire();
+            _d.acquire();
+            c->read = read;
+            c->draw = draw;
+        } else {
+            setGLHooksThreadSpecific(&gHooksNoContext);
+            egl_tls_t::setContext(EGL_NO_CONTEXT);
+        }
+    }
+    return result;
+}
+
+
+EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
+                            EGLint attribute, EGLint *value)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    ContextRef _c(ctx);
+    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+    egl_context_t * const c = get_context(ctx);
+
+    EGLBoolean result(EGL_TRUE);
+    if (attribute == EGL_CONFIG_ID) {
+        *value = dp->configs[intptr_t(c->config)].configId;
+    } else {
+        // We need to remap EGL_CONFIG_IDs
+        result = c->cnx->egl.eglQueryContext(
+                dp->disp[c->impl].dpy, c->context, attribute, value);
+    }
+
+    return result;
+}
+
+EGLContext eglGetCurrentContext(void)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_CONTEXT.
+
+    clearError();
+
+    EGLContext ctx = getContext();
+    return ctx;
+}
+
+EGLSurface eglGetCurrentSurface(EGLint readdraw)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_SURFACE.
+
+    clearError();
+
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
+        switch (readdraw) {
+            case EGL_READ: return c->read;
+            case EGL_DRAW: return c->draw;            
+            default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+        }
+    }
+    return EGL_NO_SURFACE;
+}
+
+EGLDisplay eglGetCurrentDisplay(void)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_DISPLAY.
+
+    clearError();
+
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
+        return c->dpy;
+    }
+    return EGL_NO_DISPLAY;
+}
+
+EGLBoolean eglWaitGL(void)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+
+    clearError();
+
+    EGLBoolean res = EGL_TRUE;
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        if (uint32_t(c->impl)>=2)
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        egl_connection_t* const cnx = &gEGLImpl[c->impl];
+        if (!cnx->dso) 
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        res = cnx->egl.eglWaitGL();
+    }
+    return res;
+}
+
+EGLBoolean eglWaitNative(EGLint engine)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+
+    clearError();
+
+    EGLBoolean res = EGL_TRUE;
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        if (uint32_t(c->impl)>=2)
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        egl_connection_t* const cnx = &gEGLImpl[c->impl];
+        if (!cnx->dso) 
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        res = cnx->egl.eglWaitNative(engine);
+    }
+    return res;
+}
+
+EGLint eglGetError(void)
+{
+    EGLint result = EGL_SUCCESS;
+    EGLint err;
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        err = EGL_SUCCESS;
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso)
+            err = cnx->egl.eglGetError();
+        if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
+            result = err;
+    }
+    err = egl_tls_t::getError();
+    if (result == EGL_SUCCESS)
+        result = err;
+    return result;
+}
+
+// Note: Similar implementations of these functions also exist in
+// gl2.cpp and gl.cpp, and are used by applications that call the
+// exported entry points directly.
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
+static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
+
+static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage =
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    glEGLImageTargetTexture2DOES_impl(target, implImage);
+}
+
+static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage =
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
+}
+
+__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
+{
+    // eglGetProcAddress() could be the very first function called
+    // in which case we must make sure we've initialized ourselves, this
+    // happens the first time egl_get_display() is called.
+
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        setError(EGL_BAD_PARAMETER, NULL);
+        return  NULL;
+    }
+
+    __eglMustCastToProperFunctionPointerType addr;
+    addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
+    if (addr) return addr;
+
+    // this protects accesses to sGLExtentionMap and sGLExtentionSlot
+    pthread_mutex_lock(&sExtensionMapMutex);
+
+        /*
+         * Since eglGetProcAddress() is not associated to anything, it needs
+         * to return a function pointer that "works" regardless of what
+         * the current context is.
+         *
+         * For this reason, we return a "forwarder", a small stub that takes
+         * care of calling the function associated with the context
+         * currently bound.
+         *
+         * We first look for extensions we've already resolved, if we're seeing
+         * this extension for the first time, we go through all our
+         * implementations and call eglGetProcAddress() and record the
+         * result in the appropriate implementation hooks and return the
+         * address of the forwarder corresponding to that hook set.
+         *
+         */
+
+        const String8 name(procname);
+        addr = sGLExtentionMap.valueFor(name);
+        const int slot = sGLExtentionSlot;
+
+        LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
+                "no more slots for eglGetProcAddress(\"%s\")",
+                procname);
+
+        if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
+            bool found = false;
+            for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+                egl_connection_t* const cnx = &gEGLImpl[i];
+                if (cnx->dso && cnx->egl.eglGetProcAddress) {
+                    found = true;
+                    // Extensions are independent of the bound context
+                    cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
+                    cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
+#if EGL_TRACE
+                    gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
+#endif
+                            cnx->egl.eglGetProcAddress(procname);
+                }
+            }
+            if (found) {
+                addr = gExtensionForwarders[slot];
+
+                if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
+                    glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
+                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
+                }
+                if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
+                    glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
+                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
+                }
+
+                sGLExtentionMap.add(name, addr);
+                sGLExtentionSlot++;
+            }
+        }
+
+    pthread_mutex_unlock(&sExtensionMapMutex);
+    return addr;
+}
+
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+{
+    EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
+    if (gEGLDebugLevel > 0)
+        Debug_eglSwapBuffers(dpy, draw);
+
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(draw);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(draw);
+    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
+}
+
+EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
+                            NativePixmapType target)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    return s->cnx->egl.eglCopyBuffers(
+            dp->disp[s->impl].dpy, s->surface, target);
+}
+
+const char* eglQueryString(EGLDisplay dpy, EGLint name)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return (const char *) NULL;
+
+    switch (name) {
+        case EGL_VENDOR:
+            return sVendorString;
+        case EGL_VERSION:
+            return sVersionString;
+        case EGL_EXTENSIONS:
+            return sExtensionString;
+        case EGL_CLIENT_APIS:
+            return sClientApiString;
+    }
+    return setError(EGL_BAD_PARAMETER, (const char *)0);
+}
+
+
+// ----------------------------------------------------------------------------
+// EGL 1.1
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSurfaceAttrib(
+        EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglSurfaceAttrib) {
+        return s->cnx->egl.eglSurfaceAttrib(
+                dp->disp[s->impl].dpy, s->surface, attribute, value);
+    }
+    return setError(EGL_BAD_SURFACE, EGL_FALSE);
+}
+
+EGLBoolean eglBindTexImage(
+        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglBindTexImage) {
+        return s->cnx->egl.eglBindTexImage(
+                dp->disp[s->impl].dpy, s->surface, buffer);
+    }
+    return setError(EGL_BAD_SURFACE, EGL_FALSE);
+}
+
+EGLBoolean eglReleaseTexImage(
+        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglReleaseTexImage) {
+        return s->cnx->egl.eglReleaseTexImage(
+                dp->disp[s->impl].dpy, s->surface, buffer);
+    }
+    return setError(EGL_BAD_SURFACE, EGL_FALSE);
+}
+
+EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    EGLBoolean res = EGL_TRUE;
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglSwapInterval) {
+                if (cnx->egl.eglSwapInterval(
+                        dp->disp[i].dpy, interval) == EGL_FALSE) {
+                    res = EGL_FALSE;
+                }
+            }
+        }
+    }
+    return res;
+}
+
+
+// ----------------------------------------------------------------------------
+// EGL 1.2
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglWaitClient(void)
+{
+    clearError();
+
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+    EGLBoolean res = EGL_TRUE;
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        if (uint32_t(c->impl)>=2)
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        egl_connection_t* const cnx = &gEGLImpl[c->impl];
+        if (!cnx->dso) 
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        if (cnx->egl.eglWaitClient) {
+            res = cnx->egl.eglWaitClient();
+        } else {
+            res = cnx->egl.eglWaitGL();
+        }
+    }
+    return res;
+}
+
+EGLBoolean eglBindAPI(EGLenum api)
+{
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    // bind this API on all EGLs
+    EGLBoolean res = EGL_TRUE;
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglBindAPI) {
+                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
+                    res = EGL_FALSE;
+                }
+            }
+        }
+    }
+    return res;
+}
+
+EGLenum eglQueryAPI(void)
+{
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglQueryAPI) {
+                // the first one we find is okay, because they all
+                // should be the same
+                return cnx->egl.eglQueryAPI();
+            }
+        }
+    }
+    // or, it can only be OpenGL ES
+    return EGL_OPENGL_ES_API;
+}
+
+EGLBoolean eglReleaseThread(void)
+{
+    clearError();
+
+    // If there is context bound to the thread, release it
+    loseCurrent(get_context(getContext()));
+
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglReleaseThread) {
+                cnx->egl.eglReleaseThread();
+            }
+        }
+    }
+    egl_tls_t::clearTLS();
+    dbgReleaseThread();
+    return EGL_TRUE;
+}
+
+EGLSurface eglCreatePbufferFromClientBuffer(
+          EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+          EGLConfig config, const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (!cnx) return EGL_FALSE;
+    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
+        return cnx->egl.eglCreatePbufferFromClientBuffer(
+                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+                buftype, buffer,
+                dp->configs[intptr_t(config)].config, attrib_list);
+    }
+    return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
+}
+
+// ----------------------------------------------------------------------------
+// EGL_EGLEXT_VERSION 3
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+        const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglLockSurfaceKHR) {
+        return s->cnx->egl.eglLockSurfaceKHR(
+                dp->disp[s->impl].dpy, s->surface, attrib_list);
+    }
+    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglUnlockSurfaceKHR) {
+        return s->cnx->egl.eglUnlockSurfaceKHR(
+                dp->disp[s->impl].dpy, s->surface);
+    }
+    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+        EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_NO_IMAGE_KHR;
+
+    if (ctx != EGL_NO_CONTEXT) {
+        ContextRef _c(ctx);
+        if (!_c.get())
+            return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+        egl_context_t * const c = get_context(ctx);
+        // since we have an EGLContext, we know which implementation to use
+        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
+                dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
+        if (image == EGL_NO_IMAGE_KHR)
+            return image;
+            
+        egl_image_t* result = new egl_image_t(dpy, ctx);
+        result->images[c->impl] = image;
+        return (EGLImageKHR)result;
+    } else {
+        // EGL_NO_CONTEXT is a valid parameter
+
+        /* Since we don't have a way to know which implementation to call,
+         * we're calling all of them. If at least one of the implementation
+         * succeeded, this is a success.
+         */
+
+        EGLint currentError = eglGetError();
+
+        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
+        bool success = false;
+        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+            egl_connection_t* const cnx = &gEGLImpl[i];
+            implImages[i] = EGL_NO_IMAGE_KHR;
+            if (cnx->dso) {
+                if (cnx->egl.eglCreateImageKHR) {
+                    implImages[i] = cnx->egl.eglCreateImageKHR(
+                            dp->disp[i].dpy, ctx, target, buffer, attrib_list);
+                    if (implImages[i] != EGL_NO_IMAGE_KHR) {
+                        success = true;
+                    }
+                }
+            }
+        }
+
+        if (!success) {
+            // failure, if there was an error when we entered this function,
+            // the error flag must not be updated.
+            // Otherwise, the error is whatever happened in the implementation
+            // that faulted.
+            if (currentError != EGL_SUCCESS) {
+                setError(currentError, EGL_NO_IMAGE_KHR);
+            }
+            return EGL_NO_IMAGE_KHR;
+        } else {
+            // In case of success, we need to clear all error flags
+            // (especially those caused by the implementation that didn't
+            // succeed). TODO: we could avoid this if we knew this was
+            // a "full" success (all implementation succeeded).
+            eglGetError();
+        }
+
+        egl_image_t* result = new egl_image_t(dpy, ctx);
+        memcpy(result->images, implImages, sizeof(implImages));
+        return (EGLImageKHR)result;
+    }
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    ImageRef _i(img);
+    if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+    egl_image_t* image = get_image(img);
+    bool success = false;
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (image->images[i] != EGL_NO_IMAGE_KHR) {
+            if (cnx->dso) {
+                if (cnx->egl.eglDestroyImageKHR) {
+                    if (cnx->egl.eglDestroyImageKHR(
+                            dp->disp[i].dpy, image->images[i])) {
+                        success = true;
+                    }
+                }
+            }
+        }
+    }
+    if (!success)
+        return EGL_FALSE;
+
+    _i.terminate();
+
+    return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// EGL_EGLEXT_VERSION 5
+// ----------------------------------------------------------------------------
+
+
+EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_NO_SYNC_KHR;
+
+    EGLContext ctx = eglGetCurrentContext();
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
+
+    egl_context_t * const c = get_context(ctx);
+    EGLSyncKHR result = EGL_NO_SYNC_KHR;
+    if (c->cnx->egl.eglCreateSyncKHR) {
+        EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
+                dp->disp[c->impl].dpy, type, attrib_list);
+        if (sync == EGL_NO_SYNC_KHR)
+            return sync;
+        result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
+    }
+    return (EGLSyncKHR)result;
+}
+
+EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SyncRef _s(sync);
+    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    egl_sync_t* syncObject = get_sync(sync);
+
+    EGLContext ctx = syncObject->context;
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+    EGLBoolean result = EGL_FALSE;
+    egl_context_t * const c = get_context(ctx);
+    if (c->cnx->egl.eglDestroySyncKHR) {
+        result = c->cnx->egl.eglDestroySyncKHR(
+                dp->disp[c->impl].dpy, syncObject->sync);
+        if (result)
+            _s.terminate();
+    }
+    return result;
+}
+
+EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SyncRef _s(sync);
+    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    egl_sync_t* syncObject = get_sync(sync);
+
+    EGLContext ctx = syncObject->context;
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+    egl_context_t * const c = get_context(ctx);
+    if (c->cnx->egl.eglClientWaitSyncKHR) {
+        return c->cnx->egl.eglClientWaitSyncKHR(
+                dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SyncRef _s(sync);
+    if (!_s.get())
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+    egl_sync_t* syncObject = get_sync(sync);
+    EGLContext ctx = syncObject->context;
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+    egl_context_t * const c = get_context(ctx);
+    if (c->cnx->egl.eglGetSyncAttribKHR) {
+        return c->cnx->egl.eglGetSyncAttribKHR(
+                dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
+    }
+
+    return EGL_FALSE;
+}
+
+// ----------------------------------------------------------------------------
+// ANDROID extensions
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
+        EGLint left, EGLint top, EGLint width, EGLint height)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(draw);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(draw);
+    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
+        return s->cnx->egl.eglSetSwapRectangleANDROID(
+                dp->disp[s->impl].dpy, s->surface, left, top, width, height);
+    }
+    return setError(EGL_BAD_DISPLAY, NULL);
+}
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
new file mode 100644
index 0000000..83aafa6
--- /dev/null
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -0,0 +1,276 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#include "egl_display.h"
+#include "egl_object.h"
+#include "egl_tls.h"
+#include "egl_impl.h"
+#include "Loader.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+extern void initEglTraceLevel();
+extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
+
+static int cmp_configs(const void* a, const void *b) {
+    const egl_config_t& c0 = *(egl_config_t const *)a;
+    const egl_config_t& c1 = *(egl_config_t const *)b;
+    return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
+}
+
+// ----------------------------------------------------------------------------
+
+egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
+
+egl_display_t::egl_display_t() :
+    magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) {
+}
+
+egl_display_t::~egl_display_t() {
+    magic = 0;
+}
+
+egl_display_t* egl_display_t::get(EGLDisplay dpy) {
+    uintptr_t index = uintptr_t(dpy)-1U;
+    return (index >= NUM_DISPLAYS) ? NULL : &sDisplay[index];
+}
+
+void egl_display_t::addObject(egl_object_t* object) {
+    Mutex::Autolock _l(lock);
+    objects.add(object);
+}
+
+void egl_display_t::removeObject(egl_object_t* object) {
+    Mutex::Autolock _l(lock);
+    objects.remove(object);
+}
+
+bool egl_display_t::getObject(egl_object_t* object) {
+    Mutex::Autolock _l(lock);
+    if (objects.indexOf(object) >= 0) {
+        object->incRef();
+        return true;
+    }
+    return false;
+}
+
+EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
+    if (uintptr_t(disp) >= NUM_DISPLAYS)
+        return NULL;
+
+    return sDisplay[uintptr_t(disp)].getDisplay(disp);
+}
+
+EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
+
+    Mutex::Autolock _l(lock);
+
+    // get our driver loader
+    Loader& loader(Loader::getInstance());
+
+    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso && disp[i].dpy == EGL_NO_DISPLAY) {
+            EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
+            disp[i].dpy = dpy;
+            if (dpy == EGL_NO_DISPLAY) {
+                loader.close(cnx->dso);
+                cnx->dso = NULL;
+            }
+        }
+    }
+
+    return EGLDisplay(uintptr_t(display) + 1U);
+}
+
+EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
+
+    Mutex::Autolock _l(lock);
+
+    if (refs > 0) {
+        if (major != NULL)
+            *major = VERSION_MAJOR;
+        if (minor != NULL)
+            *minor = VERSION_MINOR;
+        refs++;
+        return EGL_TRUE;
+    }
+
+#if EGL_TRACE
+
+    // Called both at early_init time and at this time. (Early_init is pre-zygote, so
+    // the information from that call may be stale.)
+    initEglTraceLevel();
+
+#endif
+
+    setGLHooksThreadSpecific(&gHooksNoContext);
+
+    // initialize each EGL and
+    // build our own extension string first, based on the extension we know
+    // and the extension supported by our client implementation
+    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        cnx->major = -1;
+        cnx->minor = -1;
+        if (!cnx->dso)
+            continue;
+
+#if defined(ADRENO130)
+#warning "Adreno-130 eglInitialize() workaround"
+        /*
+         * The ADRENO 130 driver returns a different EGLDisplay each time
+         * eglGetDisplay() is called, but also makes the EGLDisplay invalid
+         * after eglTerminate() has been called, so that eglInitialize()
+         * cannot be called again. Therefore, we need to make sure to call
+         * eglGetDisplay() before calling eglInitialize();
+         */
+        if (i == IMPL_HARDWARE) {
+            disp[i].dpy =
+            cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        }
+#endif
+
+        EGLDisplay idpy = disp[i].dpy;
+        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
+            //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
+            //        i, idpy, cnx->major, cnx->minor, cnx);
+
+            // display is now initialized
+            disp[i].state = egl_display_t::INITIALIZED;
+
+            // get the query-strings for this display for each implementation
+            disp[i].queryString.vendor = cnx->egl.eglQueryString(idpy,
+                    EGL_VENDOR);
+            disp[i].queryString.version = cnx->egl.eglQueryString(idpy,
+                    EGL_VERSION);
+            disp[i].queryString.extensions = cnx->egl.eglQueryString(idpy,
+                    EGL_EXTENSIONS);
+            disp[i].queryString.clientApi = cnx->egl.eglQueryString(idpy,
+                    EGL_CLIENT_APIS);
+
+        } else {
+            LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
+                    egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
+        }
+    }
+
+    EGLBoolean res = EGL_FALSE;
+    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
+            EGLint n;
+            if (cnx->egl.eglGetConfigs(disp[i].dpy, 0, 0, &n)) {
+                disp[i].config = (EGLConfig*) malloc(sizeof(EGLConfig) * n);
+                if (disp[i].config) {
+                    if (cnx->egl.eglGetConfigs(disp[i].dpy, disp[i].config, n,
+                            &disp[i].numConfigs)) {
+                        numTotalConfigs += n;
+                        res = EGL_TRUE;
+                    }
+                }
+            }
+        }
+    }
+
+    if (res == EGL_TRUE) {
+        configs = new egl_config_t[numTotalConfigs];
+        for (int i = 0, k = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+            egl_connection_t* const cnx = &gEGLImpl[i];
+            if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
+                for (int j = 0; j < disp[i].numConfigs; j++) {
+                    configs[k].impl = i;
+                    configs[k].config = disp[i].config[j];
+                    configs[k].configId = k + 1; // CONFIG_ID start at 1
+                    // store the implementation's CONFIG_ID
+                    cnx->egl.eglGetConfigAttrib(disp[i].dpy, disp[i].config[j],
+                            EGL_CONFIG_ID, &configs[k].implConfigId);
+                    k++;
+                }
+            }
+        }
+
+        // sort our configurations so we can do binary-searches
+        qsort(configs, numTotalConfigs, sizeof(egl_config_t), cmp_configs);
+
+        refs++;
+        if (major != NULL)
+            *major = VERSION_MAJOR;
+        if (minor != NULL)
+            *minor = VERSION_MINOR;
+        return EGL_TRUE;
+    }
+    return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+}
+
+EGLBoolean egl_display_t::terminate() {
+
+    Mutex::Autolock _l(lock);
+
+    if (refs == 0) {
+        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+    }
+
+    // this is specific to Android, display termination is ref-counted.
+    if (refs > 1) {
+        refs--;
+        return EGL_TRUE;
+    }
+
+    EGLBoolean res = EGL_FALSE;
+    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso && disp[i].state == egl_display_t::INITIALIZED) {
+            if (cnx->egl.eglTerminate(disp[i].dpy) == EGL_FALSE) {
+                LOGW("%d: eglTerminate(%p) failed (%s)", i, disp[i].dpy,
+                        egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
+            }
+            // REVISIT: it's unclear what to do if eglTerminate() fails
+            free(disp[i].config);
+
+            disp[i].numConfigs = 0;
+            disp[i].config = 0;
+            disp[i].state = egl_display_t::TERMINATED;
+
+            res = EGL_TRUE;
+        }
+    }
+
+    // Mark all objects remaining in the list as terminated, unless
+    // there are no reference to them, it which case, we're free to
+    // delete them.
+    size_t count = objects.size();
+    LOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
+    for (size_t i=0 ; i<count ; i++) {
+        egl_object_t* o = objects.itemAt(i);
+        o->destroy();
+    }
+
+    // this marks all object handles are "terminated"
+    objects.clear();
+
+    refs--;
+    numTotalConfigs = 0;
+    delete[] configs;
+    return res;
+}
+
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
new file mode 100644
index 0000000..113595f
--- /dev/null
+++ b/opengl/libs/EGL/egl_display.h
@@ -0,0 +1,144 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_EGL_DISPLAY_H
+#define ANDROID_EGL_DISPLAY_H
+
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
+
+#include "egldefs.h"
+#include "hooks.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class egl_object_t;
+class egl_connection_t;
+
+// ----------------------------------------------------------------------------
+
+struct egl_config_t {
+    egl_config_t() {}
+    egl_config_t(int impl, EGLConfig config)
+        : impl(impl), config(config), configId(0), implConfigId(0) { }
+    int         impl;           // the implementation this config is for
+    EGLConfig   config;         // the implementation's EGLConfig
+    EGLint      configId;       // our CONFIG_ID
+    EGLint      implConfigId;   // the implementation's CONFIG_ID
+    inline bool operator < (const egl_config_t& rhs) const {
+        if (impl < rhs.impl) return true;
+        if (impl > rhs.impl) return false;
+        return config < rhs.config;
+    }
+};
+
+// ----------------------------------------------------------------------------
+
+class egl_display_t {
+    static egl_display_t sDisplay[NUM_DISPLAYS];
+    EGLDisplay getDisplay(EGLNativeDisplayType display);
+
+public:
+    enum {
+        NOT_INITIALIZED = 0,
+        INITIALIZED     = 1,
+        TERMINATED      = 2
+    };
+
+    egl_display_t();
+    ~egl_display_t();
+
+    EGLBoolean initialize(EGLint *major, EGLint *minor);
+    EGLBoolean terminate();
+
+    // add object to this display's list
+    void addObject(egl_object_t* object);
+    // remove object from this display's list
+    void removeObject(egl_object_t* object);
+    // add reference to this object. returns true if this is a valid object.
+    bool getObject(egl_object_t* object);
+
+
+    static egl_display_t* get(EGLDisplay dpy);
+    static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp);
+
+    inline bool isReady() const { return (refs > 0); }
+    inline bool isValid() const { return magic == '_dpy'; }
+    inline bool isAlive() const { return isValid(); }
+
+    struct strings_t {
+        char const * vendor;
+        char const * version;
+        char const * clientApi;
+        char const * extensions;
+    };
+
+    struct DisplayImpl {
+        DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
+                        state(NOT_INITIALIZED), numConfigs(0) { }
+        EGLDisplay  dpy;
+        EGLConfig*  config;
+        EGLint      state;
+        EGLint      numConfigs;
+        strings_t   queryString;
+    };
+
+private:
+    uint32_t        magic;
+
+public:
+    DisplayImpl     disp[IMPL_NUM_IMPLEMENTATIONS];
+    EGLint          numTotalConfigs;
+    egl_config_t*   configs;
+
+private:
+    uint32_t        refs;
+    Mutex           lock;
+    SortedVector<egl_object_t*> objects;
+};
+
+// ----------------------------------------------------------------------------
+
+inline egl_display_t* get_display(EGLDisplay dpy) {
+    return egl_display_t::get(dpy);
+}
+
+// ----------------------------------------------------------------------------
+
+egl_display_t* validate_display(EGLDisplay dpy);
+egl_connection_t* validate_display_config(EGLDisplay dpy,
+        EGLConfig config, egl_display_t const*& dp);
+EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx);
+EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface);
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif // ANDROID_EGL_DISPLAY_H
+
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
new file mode 100644
index 0000000..dbf9a01
--- /dev/null
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -0,0 +1,66 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/threads.h>
+
+#include "egl_object.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+egl_object_t::egl_object_t(egl_display_t* disp) :
+    display(disp), count(1) {
+    // NOTE: this does an implicit incRef
+    display->addObject(this);
+}
+
+egl_object_t::~egl_object_t() {
+}
+
+void egl_object_t::terminate() {
+    // this marks the object as "terminated"
+    display->removeObject(this);
+    if (decRef() == 1) {
+        // shouldn't happen because this is called from LocalRef
+        LOGE("egl_object_t::terminate() removed the last reference!");
+    }
+}
+
+void egl_object_t::destroy() {
+    if (decRef() == 1) {
+        delete this;
+    }
+}
+
+bool egl_object_t::get() {
+    // used by LocalRef, this does an incRef() atomically with
+    // checking that the object is valid.
+    return display->getObject(this);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
new file mode 100644
index 0000000..3459a8a
--- /dev/null
+++ b/opengl/libs/EGL/egl_object.h
@@ -0,0 +1,235 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_EGL_OBJECT_H
+#define ANDROID_EGL_OBJECT_H
+
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/threads.h>
+
+#include <system/window.h>
+
+#include "egl_display.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+struct egl_display_t;
+
+class egl_object_t {
+    egl_display_t *display;
+    mutable volatile int32_t count;
+
+protected:
+    virtual ~egl_object_t();
+
+public:
+    egl_object_t(egl_display_t* display);
+    void destroy();
+
+    inline int32_t incRef() { return android_atomic_inc(&count); }
+    inline int32_t decRef() { return android_atomic_dec(&count); }
+
+private:
+    void terminate();
+    bool get();
+
+public:
+    template <typename N, typename T>
+    class LocalRef {
+        egl_object_t* ref;
+        LocalRef();
+        LocalRef(const LocalRef* rhs);
+    public:
+        ~LocalRef();
+        explicit LocalRef(egl_object_t* rhs);
+        explicit LocalRef(T o) : ref(0) {
+            egl_object_t* native = reinterpret_cast<N*>(o);
+            if (o && native->get()) {
+                ref = native;
+            }
+        }
+        inline N* get() {
+            return static_cast<N*>(ref);
+        }
+        void acquire() const;
+        void release() const;
+        void terminate();
+    };
+    template <typename N, typename T>
+    friend class LocalRef;
+};
+
+template<typename N, typename T>
+egl_object_t::LocalRef<N, T>::LocalRef(egl_object_t* rhs) : ref(rhs) {
+    if (ref) {
+        ref->incRef();
+    }
+}
+
+template <typename N, typename T>
+egl_object_t::LocalRef<N,T>::~LocalRef() {
+    if (ref) {
+        ref->destroy();
+    }
+}
+
+template <typename N, typename T>
+void egl_object_t::LocalRef<N,T>::acquire() const {
+    if (ref) {
+        ref->incRef();
+    }
+}
+
+template <typename N, typename T>
+void egl_object_t::LocalRef<N,T>::release() const {
+    if (ref) {
+        if (ref->decRef() == 1) {
+            // shouldn't happen because this is called from LocalRef
+            LOGE("LocalRef::release() removed the last reference!");
+        }
+    }
+}
+
+template <typename N, typename T>
+void egl_object_t::LocalRef<N,T>::terminate() {
+    if (ref) {
+        ref->terminate();
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+class egl_surface_t: public egl_object_t {
+protected:
+    ~egl_surface_t() {}
+public:
+    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
+
+    egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
+            EGLSurface surface, int impl, egl_connection_t const* cnx) :
+        egl_object_t(get_display(dpy)), dpy(dpy), surface(surface),
+                config(config), win(win), impl(impl), cnx(cnx) {
+    }
+    EGLDisplay dpy;
+    EGLSurface surface;
+    EGLConfig config;
+    sp<ANativeWindow> win;
+    int impl;
+    egl_connection_t const* cnx;
+};
+
+class egl_context_t: public egl_object_t {
+protected:
+    ~egl_context_t() {}
+public:
+    typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
+
+    egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
+            int impl, egl_connection_t const* cnx, int version) :
+        egl_object_t(get_display(dpy)), dpy(dpy), context(context),
+                config(config), read(0), draw(0), impl(impl), cnx(cnx),
+                version(version) {
+    }
+    EGLDisplay dpy;
+    EGLContext context;
+    EGLConfig config;
+    EGLSurface read;
+    EGLSurface draw;
+    int impl;
+    egl_connection_t const* cnx;
+    int version;
+};
+
+class egl_image_t: public egl_object_t {
+protected:
+    ~egl_image_t() {}
+public:
+    typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
+
+    egl_image_t(EGLDisplay dpy, EGLContext context) :
+        egl_object_t(get_display(dpy)), dpy(dpy), context(context) {
+        memset(images, 0, sizeof(images));
+    }
+    EGLDisplay dpy;
+    EGLContext context;
+    EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
+};
+
+class egl_sync_t: public egl_object_t {
+protected:
+    ~egl_sync_t() {}
+public:
+    typedef egl_object_t::LocalRef<egl_sync_t, EGLSyncKHR> Ref;
+
+    egl_sync_t(EGLDisplay dpy, EGLContext context, EGLSyncKHR sync) :
+        egl_object_t(get_display(dpy)), dpy(dpy), context(context), sync(sync) {
+    }
+    EGLDisplay dpy;
+    EGLContext context;
+    EGLSyncKHR sync;
+};
+
+// ----------------------------------------------------------------------------
+
+typedef egl_surface_t::Ref  SurfaceRef;
+typedef egl_context_t::Ref  ContextRef;
+typedef egl_image_t::Ref    ImageRef;
+typedef egl_sync_t::Ref     SyncRef;
+
+// ----------------------------------------------------------------------------
+
+template<typename NATIVE, typename EGL>
+static inline NATIVE* egl_to_native_cast(EGL arg) {
+    return reinterpret_cast<NATIVE*>(arg);
+}
+
+static inline
+egl_surface_t* get_surface(EGLSurface surface) {
+    return egl_to_native_cast<egl_surface_t>(surface);
+}
+
+static inline
+egl_context_t* get_context(EGLContext context) {
+    return egl_to_native_cast<egl_context_t>(context);
+}
+
+static inline
+egl_image_t* get_image(EGLImageKHR image) {
+    return egl_to_native_cast<egl_image_t>(image);
+}
+
+static inline
+egl_sync_t* get_sync(EGLSyncKHR sync) {
+    return egl_to_native_cast<egl_sync_t>(sync);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif // ANDROID_EGL_OBJECT_H
+
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
new file mode 100644
index 0000000..961a61e
--- /dev/null
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -0,0 +1,133 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <pthread.h>
+
+#include <cutils/log.h>
+
+#include <EGL/egl.h>
+
+#include "egl_tls.h"
+
+
+namespace android {
+
+pthread_key_t egl_tls_t::sKey = -1;
+pthread_mutex_t egl_tls_t::sLockKey = PTHREAD_MUTEX_INITIALIZER;
+
+egl_tls_t::egl_tls_t()
+    : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE), dbg(0) {
+}
+
+const char *egl_tls_t::egl_strerror(EGLint err) {
+    switch (err) {
+        case EGL_SUCCESS:               return "EGL_SUCCESS";
+        case EGL_NOT_INITIALIZED:       return "EGL_NOT_INITIALIZED";
+        case EGL_BAD_ACCESS:            return "EGL_BAD_ACCESS";
+        case EGL_BAD_ALLOC:             return "EGL_BAD_ALLOC";
+        case EGL_BAD_ATTRIBUTE:         return "EGL_BAD_ATTRIBUTE";
+        case EGL_BAD_CONFIG:            return "EGL_BAD_CONFIG";
+        case EGL_BAD_CONTEXT:           return "EGL_BAD_CONTEXT";
+        case EGL_BAD_CURRENT_SURFACE:   return "EGL_BAD_CURRENT_SURFACE";
+        case EGL_BAD_DISPLAY:           return "EGL_BAD_DISPLAY";
+        case EGL_BAD_MATCH:             return "EGL_BAD_MATCH";
+        case EGL_BAD_NATIVE_PIXMAP:     return "EGL_BAD_NATIVE_PIXMAP";
+        case EGL_BAD_NATIVE_WINDOW:     return "EGL_BAD_NATIVE_WINDOW";
+        case EGL_BAD_PARAMETER:         return "EGL_BAD_PARAMETER";
+        case EGL_BAD_SURFACE:           return "EGL_BAD_SURFACE";
+        case EGL_CONTEXT_LOST:          return "EGL_CONTEXT_LOST";
+        default: return "UNKNOWN";
+    }
+}
+
+void egl_tls_t::validateTLSKey()
+{
+    if (sKey == -1) {
+        pthread_mutex_lock(&sLockKey);
+        if (sKey == -1)
+            pthread_key_create(&sKey, NULL);
+        pthread_mutex_unlock(&sLockKey);
+    }
+}
+
+void egl_tls_t::setErrorEtcImpl(const char* caller, int line, EGLint error) {
+    validateTLSKey();
+    egl_tls_t* tls = getTLS();
+    if (tls->error != error) {
+        LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
+        tls->error = error;
+    }
+}
+
+bool egl_tls_t::logNoContextCall() {
+    egl_tls_t* tls = getTLS();
+    if (tls->logCallWithNoContext == true) {
+        tls->logCallWithNoContext = false;
+        return true;
+    }
+    return false;
+}
+
+egl_tls_t* egl_tls_t::getTLS() {
+    egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
+    if (tls == 0) {
+        tls = new egl_tls_t;
+        pthread_setspecific(sKey, tls);
+    }
+    return tls;
+}
+
+void egl_tls_t::clearTLS() {
+    if (sKey != -1) {
+        egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
+        if (tls) {
+            delete tls;
+            pthread_setspecific(sKey, 0);
+        }
+    }
+}
+
+void egl_tls_t::clearError() {
+    // This must clear the error from all the underlying EGL implementations as
+    // well as the EGL wrapper layer.
+    eglGetError();
+}
+
+EGLint egl_tls_t::getError() {
+    if (sKey == -1)
+        return EGL_SUCCESS;
+    egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
+    if (!tls) return EGL_SUCCESS;
+    EGLint error = tls->error;
+    tls->error = EGL_SUCCESS;
+    return error;
+}
+
+void egl_tls_t::setContext(EGLContext ctx) {
+    validateTLSKey();
+    getTLS()->ctx = ctx;
+}
+
+EGLContext egl_tls_t::getContext() {
+    if (sKey == -1)
+        return EGL_NO_CONTEXT;
+    egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey);
+    if (!tls) return EGL_NO_CONTEXT;
+    return tls->ctx;
+}
+
+
+} // namespace android
diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h
new file mode 100644
index 0000000..a7989ef
--- /dev/null
+++ b/opengl/libs/EGL/egl_tls.h
@@ -0,0 +1,78 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_EGL_TLS_H
+#define ANDROID_EGL_TLS_H
+
+#include <pthread.h>
+
+#include <EGL/egl.h>
+
+#include "egldefs.h"
+#include "hooks.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class DbgContext;
+
+class egl_tls_t {
+    static pthread_key_t sKey;
+    static pthread_mutex_t sLockKey;
+
+    EGLint      error;
+    EGLContext  ctx;
+    EGLBoolean  logCallWithNoContext;
+    DbgContext* dbg;
+
+    egl_tls_t();
+    static void validateTLSKey();
+    static void setErrorEtcImpl(const char* caller, int line, EGLint error);
+
+public:
+    static egl_tls_t* getTLS();
+    static void clearTLS();
+    static void clearError();
+    static EGLint getError();
+    static void setContext(EGLContext ctx);
+    static EGLContext getContext();
+    static bool logNoContextCall();
+    static const char *egl_strerror(EGLint err);
+
+    template<typename T>
+    static T setErrorEtc(const char* caller,
+            int line, EGLint error, T returnValue) {
+        setErrorEtcImpl(caller, line, error);
+        return returnValue;
+    }
+};
+
+#define setError(_e, _r) egl_tls_t::setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
+
+// ----------------------------------------------------------------------------
+
+#if EGL_TRACE
+
+extern gl_hooks_t const* getGLTraceThreadSpecific();
+
+#endif
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif // ANDROID_EGL_TLS_H
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
new file mode 100644
index 0000000..107acd9
--- /dev/null
+++ b/opengl/libs/EGL/egldefs.h
@@ -0,0 +1,71 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_EGLDEFS_H
+#define ANDROID_EGLDEFS_H
+
+#include "hooks.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 4
+
+//  EGLDisplay are global, not attached to a given thread
+const unsigned int NUM_DISPLAYS = 1;
+
+enum {
+    IMPL_HARDWARE = 0,
+    IMPL_SOFTWARE,
+    IMPL_NUM_IMPLEMENTATIONS
+};
+
+enum {
+    GLESv1_INDEX = 0,
+    GLESv2_INDEX = 1,
+};
+
+// ----------------------------------------------------------------------------
+
+struct egl_connection_t
+{
+    inline egl_connection_t() : dso(0) { }
+    void *              dso;
+    gl_hooks_t *        hooks[2];
+    EGLint              major;
+    EGLint              minor;
+    egl_t               egl;
+};
+
+// ----------------------------------------------------------------------------
+
+extern gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+extern gl_hooks_t gHooksNoContext;
+extern pthread_key_t gGLWrapperKey;
+extern "C" void gl_unimplemented();
+
+extern char const * const gl_names[];
+extern char const * const egl_names[];
+
+extern egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif /* ANDROID_EGLDEFS_H */
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index dcf8735..f89c865 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -20,6 +20,7 @@
 
 #include <cutils/log.h>
 
+#include "egldefs.h"
 #include "hooks.h"
 
 // ----------------------------------------------------------------------------
@@ -34,7 +35,7 @@
 #undef GL_EXTENSION_LIST
 #undef GET_TLS
 
-#if defined(__arm__)
+#if USE_FAST_TLS_KEY
 
     #ifdef HAVE_ARM_TLS_REGISTER
         #define GET_TLS(reg) \
@@ -77,7 +78,7 @@
 
     #define GL_EXTENSION(_n)
 
-    #warning "eglGetProcAddress() partially supported on this architecture"
+    #warning "eglGetProcAddress() partially supported"
 
 #endif
 
diff --git a/opengl/libs/EGL/hooks.cpp b/opengl/libs/EGL/hooks.cpp
deleted file mode 100644
index 72ad6b3..0000000
--- a/opengl/libs/EGL/hooks.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/* 
- ** Copyright 2009, 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 <ctype.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <cutils/log.h>
-
-#include "hooks.h"
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-void gl_unimplemented() {
-    LOGE("called unimplemented OpenGL ES API");
-}
-
-
-// ----------------------------------------------------------------------------
-// GL / EGL hooks
-// ----------------------------------------------------------------------------
-
-#undef GL_ENTRY
-#undef EGL_ENTRY
-#define GL_ENTRY(_r, _api, ...) #_api,
-#define EGL_ENTRY(_r, _api, ...) #_api,
-
-char const * const gl_names[] = {
-    #include "entries.in"
-    NULL
-};
-
-char const * const egl_names[] = {
-    #include "egl_entries.in"
-    NULL
-};
-
-#undef GL_ENTRY
-#undef EGL_ENTRY
-
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
-
diff --git a/opengl/libs/EGL/trace.cpp b/opengl/libs/EGL/trace.cpp
index d3e96ba..0e934e2 100644
--- a/opengl/libs/EGL/trace.cpp
+++ b/opengl/libs/EGL/trace.cpp
@@ -26,6 +26,7 @@
 
 #include <cutils/log.h>
 
+#include "egl_tls.h"
 #include "hooks.h"
 
 // ----------------------------------------------------------------------------
@@ -325,7 +326,7 @@
 
 #define TRACE_GL(_type, _api, _args, _argList, ...)                       \
 static _type Tracing_ ## _api _args {                                     \
-    TraceGL(#_api, __VA_ARGS__);                                          \
+    TraceGL(#_api, __VA_ARGS__);                                        \
     gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
     return _c->_api _argList;                                             \
 }
@@ -333,11 +334,11 @@
 extern "C" {
 #include "../trace.in"
 }
+
 #undef TRACE_GL_VOID
 #undef TRACE_GL
 
 #define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
-
 EGLAPI gl_hooks_t gHooksTrace = {
     {
         #include "entries.in"
@@ -348,6 +349,48 @@
 };
 #undef GL_ENTRY
 
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+// define the ES 1.0 Debug_gl* functions as Tracing_gl functions
+#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
+static void Debug_ ## _api _args {                                      \
+    TraceGL(#_api, __VA_ARGS__);                                          \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _c->_api _argList;                                                    \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
+static _type Debug_ ## _api _args {                                     \
+    TraceGL(#_api, __VA_ARGS__);                                        \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    return _c->_api _argList;                                             \
+}
+
+extern "C" {
+#include "../debug.in"
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+// declare all Debug_gl* functions
+#define GL_ENTRY(_r, _api, ...) _r Debug_##_api ( __VA_ARGS__ );
+#include "glesv2dbg_functions.h"
+#undef GL_ENTRY
+
+#define GL_ENTRY(_r, _api, ...) Debug_ ## _api,
+EGLAPI gl_hooks_t gHooksDebug = {
+    {
+        #include "entries.in"
+    },
+    {
+        {0}
+    }
+};
+#undef GL_ENTRY
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/GLES2_dbg/Android.mk b/opengl/libs/GLES2_dbg/Android.mk
new file mode 100644
index 0000000..9f6e68c
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/Android.mk
@@ -0,0 +1,49 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    src/api.cpp \
+    src/caller.cpp \
+    src/dbgcontext.cpp \
+    src/debugger_message.pb.cpp \
+    src/egl.cpp \
+    src/server.cpp \
+    src/vertex.cpp
+
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH) \
+    $(LOCAL_PATH)/../ \
+    external/stlport/stlport \
+    external/protobuf/src \
+    external \
+    bionic
+
+#LOCAL_CFLAGS += -O0 -g -DDEBUG -UNDEBUG
+LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI
+LOCAL_STATIC_LIBRARIES := libprotobuf-cpp-2.3.0-lite liblzf
+LOCAL_SHARED_LIBRARIES := libcutils libutils libstlport
+ifeq ($(TARGET_ARCH),arm)
+	LOCAL_CFLAGS += -fstrict-aliasing
+endif
+
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+    # we need to access the private Bionic header <bionic_tls.h>
+    # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+    # behavior from the bionic Android.mk file
+    ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+    endif
+    LOCAL_C_INCLUDES += bionic/libc/private
+endif
+
+LOCAL_MODULE:= libGLESv2_dbg
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(LOCAL_PATH)/test/Android.mk
diff --git a/opengl/libs/GLES2_dbg/generate_api_cpp.py b/opengl/libs/GLES2_dbg/generate_api_cpp.py
new file mode 100755
index 0000000..96cde57
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/generate_api_cpp.py
@@ -0,0 +1,219 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+#
+# Copyright 2011, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+import sys
+
+def RemoveAnnotation(line):
+    if line.find(":") >= 0:
+        annotation = line[line.find(":"): line.find(" ", line.find(":"))]
+        return line.replace(annotation, "*")
+    else:
+        return line
+
+def generate_api(lines):
+    externs = []
+    i = 0
+    # these have been hand written
+    skipFunctions = ["glDrawArrays", "glDrawElements"]
+
+    # these have an EXTEND_Debug_* macro for getting data
+    extendFunctions = ["glCopyTexImage2D", "glCopyTexSubImage2D", "glReadPixels",
+"glShaderSource", "glTexImage2D", "glTexSubImage2D"]
+
+    # these also needs to be forwarded to DbgContext
+    contextFunctions = ["glUseProgram", "glEnableVertexAttribArray", "glDisableVertexAttribArray",
+"glVertexAttribPointer", "glBindBuffer", "glBufferData", "glBufferSubData", "glDeleteBuffers",]
+
+    for line in lines:
+        if line.find("API_ENTRY(") >= 0: # a function prototype
+            returnType = line[0: line.find(" API_ENTRY(")]
+            functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name
+            parameterList = line[line.find(")(") + 2: line.find(") {")]
+
+            #if line.find("*") >= 0:
+            #    extern = "%s Debug_%s(%s);" % (returnType, functionName, parameterList)
+            #    externs.append(extern)
+            #    continue
+
+            if functionName in skipFunctions:
+                sys.stderr.write("!\n! skipping function '%s'\n!\n" % (functionName))
+                continue
+
+            parameters = parameterList.split(',')
+            paramIndex = 0
+            if line.find("*") >= 0 and (line.find("*") < line.find(":") or line.find("*") > line.rfind(":")): # unannotated pointer
+                if not functionName in extendFunctions:
+                    # add function to list of functions that should be hand written, but generate code anyways
+                    extern = "%s Debug_%s(%s);" % (returnType, functionName, RemoveAnnotation(parameterList))
+                    sys.stderr.write("%s should be hand written\n" % (extern))
+                    print "// FIXME: this function has pointers, it should be hand written"
+                    externs.append(extern)
+
+            print "%s Debug_%s(%s)\n{" % (returnType, functionName, RemoveAnnotation(parameterList))
+            print "    glesv2debugger::Message msg;"
+
+            if parameterList == "void":
+                parameters = []
+            arguments = ""
+            paramNames = []
+            inout = ""
+            getData = ""
+
+            callerMembers = ""
+            setCallerMembers = ""
+            setMsgParameters = ""
+
+            for parameter in parameters:
+                const = parameter.find("const")
+                parameter = parameter.replace("const", "")
+                parameter = parameter.strip()
+                paramType = parameter.split(' ')[0]
+                paramName = parameter.split(' ')[1]
+                annotation = ""
+                arguments += paramName
+                if parameter.find(":") >= 0: # has annotation
+                    assert inout == "" # only one parameter should be annotated
+                    sys.stderr.write("%s is annotated: %s \n" % (functionName, paramType))
+                    inout = paramType.split(":")[2]
+                    annotation = paramType.split(":")[1]
+                    paramType = paramType.split(":")[0]
+                    count = 1
+                    countArg = ""
+                    if annotation.find("*") >= 0: # [1,n] * param
+                        count = int(annotation.split("*")[0])
+                        countArg = annotation.split("*")[1]
+                        assert countArg in paramNames
+                    elif annotation in paramNames:
+                        count = 1
+                        countArg = annotation
+                    elif annotation == "GLstring":
+                        annotation = "strlen(%s)" % (paramName)
+                    else:
+                        count = int(annotation)
+
+                    setMsgParameters += "    msg.set_arg%d(ToInt(%s));\n" % (paramIndex, paramName)
+                    if paramType.find("void") >= 0:
+                        getData += "    msg.mutable_data()->assign(reinterpret_cast<const char *>(%s), %s * sizeof(char));" % (paramName, annotation)
+                    else:
+                        getData += "    msg.mutable_data()->assign(reinterpret_cast<const char *>(%s), %s * sizeof(%s));" % (paramName, annotation, paramType)
+                    paramType += "*"
+                else:
+                    if paramType == "GLfloat" or paramType == "GLclampf" or paramType.find("*") >= 0:
+                        setMsgParameters += "    msg.set_arg%d(ToInt(%s));\n" % (paramIndex, paramName)
+                    else:
+                        setMsgParameters += "    msg.set_arg%d(%s);\n" % (paramIndex, paramName)
+                if paramIndex < len(parameters) - 1:
+                        arguments += ', '
+                if const >= 0:
+                    paramType = "const " + paramType
+                paramNames.append(paramName)
+                paramIndex += 1
+                callerMembers += "        %s %s;\n" % (paramType, paramName)
+                setCallerMembers += "    caller.%s = %s;\n" % (paramName, paramName)
+
+            print "    struct : public FunctionCall {"
+            print callerMembers
+            print "        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {"
+            if inout in ["out", "inout"]: # get timing excluding output data copy
+                print "            nsecs_t c0 = systemTime(timeMode);"
+            if returnType == "void":
+                print "            _c->%s(%s);" % (functionName, arguments)
+            else:
+                print "            const int * ret = reinterpret_cast<const int *>(_c->%s(%s));" % (functionName, arguments)
+                print "            msg.set_ret(ToInt(ret));"
+            if inout in ["out", "inout"]:
+                print "            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);"
+                print "        " + getData
+            if functionName in extendFunctions:
+                print "\
+#ifdef EXTEND_AFTER_CALL_Debug_%s\n\
+            EXTEND_AFTER_CALL_Debug_%s;\n\
+#endif" % (functionName, functionName)
+            if functionName in contextFunctions:
+                print "            getDbgContextThreadSpecific()->%s(%s);" % (functionName, arguments)
+            if returnType == "void":
+                print "            return 0;"
+            else:
+                print "            return ret;"
+            print """        }
+    } caller;"""
+            print setCallerMembers
+            print setMsgParameters
+
+            if line.find("*") >= 0 or line.find(":") >= 0:
+                print "    // FIXME: check for pointer usage"
+            if inout in ["in", "inout"]:
+                print getData
+            if functionName in extendFunctions:
+                print "\
+#ifdef EXTEND_Debug_%s\n\
+    EXTEND_Debug_%s;\n\
+#endif" % (functionName, functionName)
+            print "    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_%s);"\
+                % (functionName)
+            if returnType != "void":
+                if returnType == "GLboolean":
+                    print "    return static_cast<GLboolean>(reinterpret_cast<int>(ret));"
+                else:
+                    print "    return reinterpret_cast<%s>(ret);" % (returnType)
+            print "}\n"
+
+
+    print "// FIXME: the following functions should be written by hand"
+    for extern in externs:
+        print extern
+
+if __name__ == "__main__":
+    print """\
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+// auto generated by generate_api_cpp.py
+
+#include <utils/Debug.h>
+
+#include "src/header.h"
+#include "src/api.h"
+
+template<typename T> static int ToInt(const T & t)
+{
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(sizeof(T) == sizeof(int));
+    return (int &)t;
+}
+"""
+    lines = open("gl2_api_annotated.in").readlines()
+    generate_api(lines)
+    #lines = open("gl2ext_api.in").readlines()
+    #generate_api(lines)
+
+
diff --git a/opengl/libs/GLES2_dbg/generate_caller_cpp.py b/opengl/libs/GLES2_dbg/generate_caller_cpp.py
new file mode 100755
index 0000000..ee4208d
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/generate_caller_cpp.py
@@ -0,0 +1,199 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+#
+# Copyright 2011, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+import sys
+
+externs = []
+    
+def generate_caller(lines):
+    i = 0
+    output = ""
+    skipFunctions = []
+    
+    for line in lines:
+        if line.find("API_ENTRY(") >= 0: # a function prototype
+            returnType = line[0: line.find(" API_ENTRY(")]
+            functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name
+            parameterList = line[line.find(")(") + 2: line.find(") {")]
+            
+            #if line.find("*") >= 0:
+            #    extern = "%s Debug_%s(%s);" % (returnType, functionName, parameterList)
+            #    externs.append(extern)
+            #    continue
+            
+            if functionName in skipFunctions:
+                sys.stderr.write("!\n! skipping function '%s'\n!\n" % functionName)
+                continue
+            output += "\
+    case glesv2debugger::Message_Function_%s:\n" % functionName
+            parameters = parameterList.split(',')
+            paramIndex = 0
+            if line.find("*") >= 0 and (line.find("*") < line.find(":") or line.find("*") > line.rfind(":")): # unannotated pointer
+                # add function to list of functions that should be hand written, but generate code anyways
+                externs.append(functionName)
+                output += "\
+        ret = GenerateCall_%s(dbg, cmd, msg, prevRet);\n\
+        break;\n" % (functionName)
+                continue
+            elif line.find(":out") >= 0 or line.find(":inout") >= 0:
+                externs.append(functionName)
+                output += "\
+        ret = GenerateCall_%s(dbg, cmd, msg, prevRet);\n\
+        break; // annotated output pointers\n" % (functionName)
+                continue
+                
+            if parameterList == "void":
+                parameters = []
+            arguments = ""
+            paramNames = []
+            inout = ""
+            getData = ""
+            
+            callerMembers = ""
+
+            for parameter in parameters:
+                const = parameter.find("const")
+                parameter = parameter.replace("const", "")
+                parameter = parameter.strip()
+                paramType = parameter.split(' ')[0]
+                paramName = parameter.split(' ')[1]
+                annotation = ""
+                if parameter.find(":") >= 0: # has annotation
+                    assert inout == "" # only one parameter should be annotated
+                    sys.stderr.write("%s is annotated: %s \n" % (functionName, paramType))
+                    inout = paramType.split(":")[2]
+                    annotation = paramType.split(":")[1]
+                    paramType = paramType.split(":")[0]
+                    count = 1
+                    countArg = ""
+                    if annotation.find("*") >= 0: # [1,n] * param
+                        count = int(annotation.split("*")[0])
+                        countArg = annotation.split("*")[1]
+                        assert countArg in paramNames
+                    elif annotation in paramNames:
+                        count = 1
+                        countArg = annotation
+                    elif annotation == "GLstring":
+                        annotation = "strlen(%s)" % (paramName)
+                    else:
+                        count = int(annotation)
+            
+                    paramType += "*"
+                    arguments += "reinterpret_cast<%s>(const_cast<char *>(cmd.data().data()))" % (paramType)
+                elif paramType == "GLboolean":
+                    arguments += "GLboolean(cmd.arg%d())" % (paramIndex)
+                else:
+                    arguments += "static_cast<%s>(cmd.arg%d())" % (paramType, paramIndex)
+
+                if paramIndex < len(parameters) - 1:
+                        arguments += ", "
+                if len(arguments) - arguments.rfind("\n") > 60 :
+                    arguments += "\n\
+            "
+                if const >= 0:
+                    paramType = "const " + paramType
+                paramNames.append(paramName)
+                paramIndex += 1
+                
+            if returnType == "void":
+                output += "\
+        dbg->hooks->gl.%s(\n\
+            %s);\n\
+        break;\n" % (functionName, arguments)
+            else:
+                output += "\
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.%s(\n\
+            %s)));\n\
+        if (cmd.has_ret())\n\
+            ret = reinterpret_cast<int *>(msg.ret());\n\
+        break;\n" % (functionName, arguments)
+    return output
+
+if __name__ == "__main__":
+
+    lines = open("gl2_api_annotated.in").readlines()
+    output = generate_caller(lines)
+    
+    out = open("src/caller.cpp", "w")
+    out.write("""\
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+// auto generated by generate_caller_cpp.py
+// implement declarations in caller.h
+
+#include "header.h"
+
+namespace android {
+
+""")
+
+    for extern in externs:
+        out.write("\
+static const int * GenerateCall_%s(DbgContext * const dbg,\n\
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);\n" % (extern))
+        print("\
+static const int * GenerateCall_%s(DbgContext * const dbg,\n\
+                            const glesv2debugger::Message & cmd,\n\
+                            glesv2debugger::Message & msg, const int * const prevRet)\n\
+{ assert(0); return prevRet; }\n" % (extern))
+                     
+    out.write(
+"""
+#include "caller.h"
+
+const int * GenerateCall(DbgContext * const dbg, const glesv2debugger::Message & cmd,
+                  glesv2debugger::Message & msg, const int * const prevRet)
+{
+    LOGD("GenerateCall function=%u", cmd.function());
+    const int * ret = prevRet; // only some functions have return value
+    nsecs_t c0 = systemTime(timeMode);
+    switch (cmd.function()) {""")
+    
+    out.write(output)
+    
+    out.write("""\
+    default:
+        assert(0);
+    }
+    msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_function(cmd.function());
+    msg.set_type(glesv2debugger::Message_Type_AfterCall);
+    return ret;
+}
+
+}; // name space android {
+""")           
+    
+            
diff --git a/opengl/libs/GLES2_dbg/generate_debug_in.py b/opengl/libs/GLES2_dbg/generate_debug_in.py
new file mode 100755
index 0000000..1280c6f
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/generate_debug_in.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+#
+# Copyright 2011, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+import sys
+
+def append_functions(functions, lines):
+	i = 0
+	for line in lines:
+		if line.find("API_ENTRY(") >= 0: # a function prototype
+			returnType = line[0: line.find(" API_ENTRY(")]
+			functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name
+			parameterList = line[line.find(")(") + 2: line.find(") {")]
+			
+			functions.append(functionName)
+			#print functionName
+			continue
+				
+			parameters = parameterList.split(',')
+			paramIndex = 0
+			if line.find("*") >= 0:
+				print "// FIXME: this function has pointers, it should be hand written"
+				externs.append("%s Tracing_%s(%s);" % (returnType, functionName, parameterList))
+			print "%s Tracing_%s(%s)\n{" % (returnType, functionName, parameterList)
+			
+			if parameterList == "void":
+				parameters = []
+			
+			arguments = ""
+			 
+			for parameter in parameters:
+				parameter = parameter.replace("const", "")
+				parameter = parameter.strip()
+				paramType = parameter.split(' ')[0]
+				paramName = parameter.split(' ')[1]
+				
+				paramIndex += 1
+				
+	return functions
+	
+
+
+if __name__ == "__main__":
+	definedFunctions = []
+	lines = open("gl2_api_annotated.in").readlines()
+	definedFunctions = append_functions(definedFunctions, lines)
+	
+	output = open("../debug.in", "w")
+	lines = open("../trace.in").readlines()
+	output.write("// the following functions are not defined in GLESv2_dbg\n")
+	for line in lines:
+		functionName = ""
+		if line.find("TRACE_GL(") >= 0: # a function prototype
+			functionName = line.split(',')[1].strip()
+		elif line.find("TRACE_GL_VOID(") >= 0: # a function prototype
+			functionName = line[line.find("(") + 1: line.find(",")] #extract GL function name
+		else:
+			continue
+		if functionName in definedFunctions:
+			#print functionName
+			continue
+		else:
+			output.write(line)
+	
diff --git a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
new file mode 100755
index 0000000..535b13e
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
@@ -0,0 +1,155 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+#
+# Copyright 2011, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+
+def generate_egl_entries(output, lines, i):
+    for line in lines:
+        if line.find("EGL_ENTRY(") >= 0:
+            line = line.split(",")[1].strip() #extract EGL function name
+            output.write("        %s = %d;\n" % (line, i))
+            i += 1
+    return i
+
+
+def generate_gl_entries(output,lines,i):
+    for line in lines:
+        if line.find("API_ENTRY(") >= 0:
+            line = line[line.find("(") + 1: line.find(")")] #extract GL function name
+            output.write("        %s = %d;\n" % (line, i))
+            i += 1
+    return i
+
+
+if __name__ == "__main__":
+    output = open("debugger_message.proto",'w')
+    output.write("""\
+/*
+ * 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.
+ */
+
+// do not edit; auto generated by generate_debugger_message_proto.py
+
+package com.android.glesv2debugger;
+
+option optimize_for = LITE_RUNTIME;
+
+message Message
+{
+    required int32 context_id = 1; // GL context id
+    enum Function
+    {
+""")
+
+    i = 0;
+
+    lines = open("gl2_api_annotated.in").readlines()
+    i = generate_gl_entries(output, lines, i)
+    output.write("        // end of GL functions\n")
+
+    #lines = open("gl2ext_api.in").readlines()
+    #i = generate_gl_entries(output, lines, i)
+    #output.write("        // end of GL EXT functions\n")
+
+    lines = open("../EGL/egl_entries.in").readlines()
+    i = generate_egl_entries(output, lines, i)
+    output.write("        // end of GL EXT functions\n")
+
+    output.write("        ACK = %d;\n" % (i))
+    i += 1
+
+    output.write("        NEG = %d;\n" % (i))
+    i += 1
+
+    output.write("        CONTINUE = %d;\n" % (i))
+    i += 1
+
+    output.write("        SKIP = %d;\n" % (i))
+    i += 1
+
+    output.write("        SETPROP = %d;\n" % (i))
+    i += 1
+
+    output.write("""    }
+    required Function function = 2 [default = NEG]; // type/function of message
+    enum Type
+    {
+        BeforeCall = 0;
+        AfterCall = 1;
+        AfterGeneratedCall = 2;
+        Response = 3; // currently used for misc messages
+        CompleteCall = 4; // BeforeCall and AfterCall merged
+    }
+    required Type type = 3;
+    required bool expect_response = 4;
+    optional int32 ret = 5; // return value from previous GL call
+    optional int32 arg0 = 6; // args to GL call
+    optional int32 arg1 = 7;
+    optional int32 arg2 = 8;
+    optional int32 arg3 = 9;
+    optional int32 arg4 = 16;
+    optional int32 arg5 = 17;
+    optional int32 arg6 = 18;
+    optional int32 arg7 = 19; // glDrawArrays/Elements sets this to active number of attributes
+    optional int32 arg8 = 20;
+
+    optional bytes data = 10; // variable length data used for GL call
+    enum DataType
+    {
+        ReferencedImage = 0; // for image sourced from ReadPixels
+        NonreferencedImage = 1; // for image sourced from ReadPixels
+    };
+    // most data types can be inferred from function
+    optional DataType data_type = 23;
+    // these are used for image data when they cannot be determined from args
+    optional int32 pixel_format = 24;
+    optional int32 pixel_type = 25;
+    optional int32 image_width = 26;
+    optional int32 image_height = 27;
+
+    optional float time = 11; // duration of previous GL call (ms)
+    enum Prop
+    {
+        CaptureDraw = 0; // arg0 = number of glDrawArrays/Elements to glReadPixels
+        TimeMode = 1; // arg0 = SYSTEM_TIME_* in utils/Timers.h
+        ExpectResponse = 2; // arg0 = enum Function, arg1 = true/false
+        CaptureSwap = 3; // arg0 = number of eglSwapBuffers to glReadPixels
+        GLConstant = 4; // arg0 = GLenum, arg1 = constant; send GL impl. constants
+    };
+    optional Prop prop = 21; // used with SETPROP, value in arg0
+    optional float clock = 22; // wall clock in seconds
+}
+""")
+
+    output.close()
+
+    os.system("aprotoc --cpp_out=src --java_out=../../../../../development/tools/glesv2debugger/src debugger_message.proto")
+    os.system('mv -f "src/debugger_message.pb.cc" "src/debugger_message.pb.cpp"')
diff --git a/opengl/libs/GLES2_dbg/gl2_api_annotated.in b/opengl/libs/GLES2_dbg/gl2_api_annotated.in
new file mode 100644
index 0000000..227e2eb
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/gl2_api_annotated.in
@@ -0,0 +1,426 @@
+void API_ENTRY(glActiveTexture)(GLenum texture) {
+    CALL_GL_API(glActiveTexture, texture);
+}
+void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) {
+    CALL_GL_API(glAttachShader, program, shader);
+}
+void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const GLchar:GLstring:in name) {
+    CALL_GL_API(glBindAttribLocation, program, index, name);
+}
+void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
+    CALL_GL_API(glBindBuffer, target, buffer);
+}
+void API_ENTRY(glBindFramebuffer)(GLenum target, GLuint framebuffer) {
+    CALL_GL_API(glBindFramebuffer, target, framebuffer);
+}
+void API_ENTRY(glBindRenderbuffer)(GLenum target, GLuint renderbuffer) {
+    CALL_GL_API(glBindRenderbuffer, target, renderbuffer);
+}
+void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
+    CALL_GL_API(glBindTexture, target, texture);
+}
+void API_ENTRY(glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+    CALL_GL_API(glBlendColor, red, green, blue, alpha);
+}
+void API_ENTRY(glBlendEquation)( GLenum mode ) {
+    CALL_GL_API(glBlendEquation, mode);
+}
+void API_ENTRY(glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) {
+    CALL_GL_API(glBlendEquationSeparate, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
+    CALL_GL_API(glBlendFunc, sfactor, dfactor);
+}
+void API_ENTRY(glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+    CALL_GL_API(glBlendFuncSeparate, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid:size:in data, GLenum usage) {
+    CALL_GL_API(glBufferData, target, size, data, usage);
+}
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid:size:in data) {
+    CALL_GL_API(glBufferSubData, target, offset, size, data);
+}
+GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target) {
+    CALL_GL_API_RETURN(glCheckFramebufferStatus, target);
+}
+void API_ENTRY(glClear)(GLbitfield mask) {
+    CALL_GL_API(glClear, mask);
+}
+void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+    CALL_GL_API(glClearColor, red, green, blue, alpha);
+}
+void API_ENTRY(glClearDepthf)(GLclampf depth) {
+    CALL_GL_API(glClearDepthf, depth);
+}
+void API_ENTRY(glClearStencil)(GLint s) {
+    CALL_GL_API(glClearStencil, s);
+}
+void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+    CALL_GL_API(glColorMask, red, green, blue, alpha);
+}
+void API_ENTRY(glCompileShader)(GLuint shader) {
+    CALL_GL_API(glCompileShader, shader);
+}
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
+    CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
+    CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
+    CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, width, height, border);
+}
+void API_ENTRY(glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, width, height);
+}
+GLuint API_ENTRY(glCreateProgram)(void) {
+    CALL_GL_API_RETURN(glCreateProgram);
+}
+GLuint API_ENTRY(glCreateShader)(GLenum type) {
+    CALL_GL_API_RETURN(glCreateShader, type);
+}
+void API_ENTRY(glCullFace)(GLenum mode) {
+    CALL_GL_API(glCullFace, mode);
+}
+void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint:n:in buffers) {
+    CALL_GL_API(glDeleteBuffers, n, buffers);
+}
+void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint:n:in framebuffers) {
+    CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glDeleteProgram)(GLuint program) {
+    CALL_GL_API(glDeleteProgram, program);
+}
+void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint:n:in renderbuffers) {
+    CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glDeleteShader)(GLuint shader) {
+    CALL_GL_API(glDeleteShader, shader);
+}
+void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint:n:in textures) {
+    CALL_GL_API(glDeleteTextures, n, textures);
+}
+void API_ENTRY(glDepthFunc)(GLenum func) {
+    CALL_GL_API(glDepthFunc, func);
+}
+void API_ENTRY(glDepthMask)(GLboolean flag) {
+    CALL_GL_API(glDepthMask, flag);
+}
+void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) {
+    CALL_GL_API(glDepthRangef, zNear, zFar);
+}
+void API_ENTRY(glDetachShader)(GLuint program, GLuint shader) {
+    CALL_GL_API(glDetachShader, program, shader);
+}
+void API_ENTRY(glDisable)(GLenum cap) {
+    CALL_GL_API(glDisable, cap);
+}
+void API_ENTRY(glDisableVertexAttribArray)(GLuint index) {
+    CALL_GL_API(glDisableVertexAttribArray, index);
+}
+void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
+    CALL_GL_API(glDrawArrays, mode, first, count);
+}
+void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
+    CALL_GL_API(glDrawElements, mode, count, type, indices);
+}
+void API_ENTRY(glEnable)(GLenum cap) {
+    CALL_GL_API(glEnable, cap);
+}
+void API_ENTRY(glEnableVertexAttribArray)(GLuint index) {
+    CALL_GL_API(glEnableVertexAttribArray, index);
+}
+void API_ENTRY(glFinish)(void) {
+    CALL_GL_API(glFinish);
+}
+void API_ENTRY(glFlush)(void) {
+    CALL_GL_API(glFlush);
+}
+void API_ENTRY(glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+    CALL_GL_API(glFramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer);
+}
+void API_ENTRY(glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+    CALL_GL_API(glFramebufferTexture2D, target, attachment, textarget, texture, level);
+}
+void API_ENTRY(glFrontFace)(GLenum mode) {
+    CALL_GL_API(glFrontFace, mode);
+}
+void API_ENTRY(glGenBuffers)(GLsizei n, GLuint:n:out buffers) {
+    CALL_GL_API(glGenBuffers, n, buffers);
+}
+void API_ENTRY(glGenerateMipmap)(GLenum target) {
+    CALL_GL_API(glGenerateMipmap, target);
+}
+void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint:n:out framebuffers) {
+    CALL_GL_API(glGenFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint:n:out renderbuffers) {
+    CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint:n:out textures) {
+    CALL_GL_API(glGenTextures, n, textures);
+}
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar:GLstring:in name) {
+    CALL_GL_API(glGetActiveAttrib, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar:GLstring:in name) {
+    CALL_GL_API(glGetActiveUniform, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+    CALL_GL_API(glGetAttachedShaders, program, maxcount, count, shaders);
+}
+int API_ENTRY(glGetAttribLocation)(GLuint program, const GLchar:GLstring:in name) {
+    CALL_GL_API_RETURN(glGetAttribLocation, program, name);
+}
+void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean* params) {
+    CALL_GL_API(glGetBooleanv, pname, params);
+}
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+}
+GLenum API_ENTRY(glGetError)(void) {
+    CALL_GL_API_RETURN(glGetError);
+}
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetFloatv, pname, params);
+}
+void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
+}
+void API_ENTRY(glGetIntegerv)(GLenum pname, GLint* params) {
+    CALL_GL_API(glGetIntegerv, pname, params);
+}
+void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint:1:out params) {
+    CALL_GL_API(glGetProgramiv, program, pname, params);
+}
+void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, GLchar:GLstring:out infolog) {
+    CALL_GL_API(glGetProgramInfoLog, program, bufsize, length, infolog);
+}
+void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetShaderiv)(GLuint shader, GLenum pname, GLint:1:out params) {
+    CALL_GL_API(glGetShaderiv, shader, pname, params);
+}
+void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar:GLstring:out infolog) {
+    CALL_GL_API(glGetShaderInfoLog, shader, bufsize, length, infolog);
+}
+void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
+    CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
+}
+void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar:GLstring:out source) {
+    CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
+}
+const GLubyte* API_ENTRY(glGetString)(GLenum name) {
+    CALL_GL_API_RETURN(glGetString, name);
+}
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetTexParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat* params) {
+    CALL_GL_API(glGetUniformfv, program, location, params);
+}
+void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint* params) {
+    CALL_GL_API(glGetUniformiv, program, location, params);
+}
+int API_ENTRY(glGetUniformLocation)(GLuint program, const GLchar:GLstring:in name) {
+    CALL_GL_API_RETURN(glGetUniformLocation, program, name);
+}
+void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetVertexAttribfv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetVertexAttribiv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer) {
+    CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
+}
+void API_ENTRY(glHint)(GLenum target, GLenum mode) {
+    CALL_GL_API(glHint, target, mode);
+}
+GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) {
+    CALL_GL_API_RETURN(glIsBuffer, buffer);
+}
+GLboolean API_ENTRY(glIsEnabled)(GLenum cap) {
+    CALL_GL_API_RETURN(glIsEnabled, cap);
+}
+GLboolean API_ENTRY(glIsFramebuffer)(GLuint framebuffer) {
+    CALL_GL_API_RETURN(glIsFramebuffer, framebuffer);
+}
+GLboolean API_ENTRY(glIsProgram)(GLuint program) {
+    CALL_GL_API_RETURN(glIsProgram, program);
+}
+GLboolean API_ENTRY(glIsRenderbuffer)(GLuint renderbuffer) {
+    CALL_GL_API_RETURN(glIsRenderbuffer, renderbuffer);
+}
+GLboolean API_ENTRY(glIsShader)(GLuint shader) {
+    CALL_GL_API_RETURN(glIsShader, shader);
+}
+GLboolean API_ENTRY(glIsTexture)(GLuint texture) {
+    CALL_GL_API_RETURN(glIsTexture, texture);
+}
+void API_ENTRY(glLineWidth)(GLfloat width) {
+    CALL_GL_API(glLineWidth, width);
+}
+void API_ENTRY(glLinkProgram)(GLuint program) {
+    CALL_GL_API(glLinkProgram, program);
+}
+void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
+    CALL_GL_API(glPixelStorei, pname, param);
+}
+void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
+    CALL_GL_API(glPolygonOffset, factor, units);
+}
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
+    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
+}
+void API_ENTRY(glReleaseShaderCompiler)(void) {
+    CALL_GL_API(glReleaseShaderCompiler);
+}
+void API_ENTRY(glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+    CALL_GL_API(glRenderbufferStorage, target, internalformat, width, height);
+}
+void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
+    CALL_GL_API(glSampleCoverage, value, invert);
+}
+void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glScissor, x, y, width, height);
+}
+void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) {
+    CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length);
+}
+void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) {
+    CALL_GL_API(glShaderSource, shader, count, string, length);
+}
+void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glStencilFunc, func, ref, mask);
+}
+void API_ENTRY(glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glStencilFuncSeparate, face, func, ref, mask);
+}
+void API_ENTRY(glStencilMask)(GLuint mask) {
+    CALL_GL_API(glStencilMask, mask);
+}
+void API_ENTRY(glStencilMaskSeparate)(GLenum face, GLuint mask) {
+    CALL_GL_API(glStencilMaskSeparate, face, mask);
+}
+void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
+    CALL_GL_API(glStencilOp, fail, zfail, zpass);
+}
+void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+    CALL_GL_API(glStencilOpSeparate, face, fail, zfail, zpass);
+}
+void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) {
+    CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels);
+}
+void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
+    CALL_GL_API(glTexParameterf, target, pname, param);
+}
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) {
+    CALL_GL_API(glTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
+    CALL_GL_API(glTexParameteri, target, pname, param);
+}
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) {
+    CALL_GL_API(glTexParameteriv, target, pname, params);
+}
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) {
+    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+void API_ENTRY(glUniform1f)(GLint location, GLfloat x) {
+    CALL_GL_API(glUniform1f, location, x);
+}
+void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat:1*count:in v) {
+    CALL_GL_API(glUniform1fv, location, count, v);
+}
+void API_ENTRY(glUniform1i)(GLint location, GLint x) {
+    CALL_GL_API(glUniform1i, location, x);
+}
+void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint:1*count:in v) {
+    CALL_GL_API(glUniform1iv, location, count, v);
+}
+void API_ENTRY(glUniform2f)(GLint location, GLfloat x, GLfloat y) {
+    CALL_GL_API(glUniform2f, location, x, y);
+}
+void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat:2*count:in v) {
+    CALL_GL_API(glUniform2fv, location, count, v);
+}
+void API_ENTRY(glUniform2i)(GLint location, GLint x, GLint y) {
+    CALL_GL_API(glUniform2i, location, x, y);
+}
+void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint:2*count:in v) {
+    CALL_GL_API(glUniform2iv, location, count, v);
+}
+void API_ENTRY(glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glUniform3f, location, x, y, z);
+}
+void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat:3*count:in v) {
+    CALL_GL_API(glUniform3fv, location, count, v);
+}
+void API_ENTRY(glUniform3i)(GLint location, GLint x, GLint y, GLint z) {
+    CALL_GL_API(glUniform3i, location, x, y, z);
+}
+void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint:3*count:in v) {
+    CALL_GL_API(glUniform3iv, location, count, v);
+}
+void API_ENTRY(glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    CALL_GL_API(glUniform4f, location, x, y, z, w);
+}
+void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat:4*count:in v) {
+    CALL_GL_API(glUniform4fv, location, count, v);
+}
+void API_ENTRY(glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w) {
+    CALL_GL_API(glUniform4i, location, x, y, z, w);
+}
+void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint:4*count:in v) {
+    CALL_GL_API(glUniform4iv, location, count, v);
+}
+void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat:4*count:in value) {
+    CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat:9*count:in value) {
+    CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat:16*count:in value) {
+    CALL_GL_API(glUniformMatrix4fv, location, count, transpose, value);
+}
+void API_ENTRY(glUseProgram)(GLuint program) {
+    CALL_GL_API(glUseProgram, program);
+}
+void API_ENTRY(glValidateProgram)(GLuint program) {
+    CALL_GL_API(glValidateProgram, program);
+}
+void API_ENTRY(glVertexAttrib1f)(GLuint indx, GLfloat x) {
+    CALL_GL_API(glVertexAttrib1f, indx, x);
+}
+void API_ENTRY(glVertexAttrib1fv)(GLuint indx, const GLfloat:1:in values) {
+    CALL_GL_API(glVertexAttrib1fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y) {
+    CALL_GL_API(glVertexAttrib2f, indx, x, y);
+}
+void API_ENTRY(glVertexAttrib2fv)(GLuint indx, const GLfloat:2:in values) {
+    CALL_GL_API(glVertexAttrib2fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glVertexAttrib3f, indx, x, y, z);
+}
+void API_ENTRY(glVertexAttrib3fv)(GLuint indx, const GLfloat:3:in values) {
+    CALL_GL_API(glVertexAttrib3fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    CALL_GL_API(glVertexAttrib4f, indx, x, y, z, w);
+}
+void API_ENTRY(glVertexAttrib4fv)(GLuint indx, const GLfloat:4:in values) {
+    CALL_GL_API(glVertexAttrib4fv, indx, values);
+}
+void API_ENTRY(glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) {
+    CALL_GL_API(glVertexAttribPointer, indx, size, type, normalized, stride, ptr);
+}
+void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glViewport, x, y, width, height);
+}
diff --git a/opengl/libs/GLES2_dbg/src/api.cpp b/opengl/libs/GLES2_dbg/src/api.cpp
new file mode 100644
index 0000000..c483547
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/api.cpp
@@ -0,0 +1,3540 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+ 
+// auto generated by generate_api_cpp.py
+
+#include <utils/Debug.h>
+
+#include "src/header.h"
+#include "src/api.h"
+
+template<typename T> static int ToInt(const T & t)
+{
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(sizeof(T) == sizeof(int));
+    return (int &)t;
+}
+
+void Debug_glActiveTexture(GLenum texture)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glActiveTexture(texture);
+            return 0;
+        }
+    } caller;
+    caller.texture = texture;
+
+    msg.set_arg0(texture);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glActiveTexture);
+}
+
+void Debug_glAttachShader(GLuint program, GLuint shader)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glAttachShader(program, shader);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.shader = shader;
+
+    msg.set_arg0(program);
+    msg.set_arg1(shader);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glAttachShader);
+}
+
+void Debug_glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindAttribLocation(program, index, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBindAttribLocation);
+}
+
+void Debug_glBindBuffer(GLenum target, GLuint buffer)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint buffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindBuffer(target, buffer);
+            getDbgContextThreadSpecific()->glBindBuffer(target, buffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.buffer = buffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(buffer);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBindBuffer);
+}
+
+void Debug_glBindFramebuffer(GLenum target, GLuint framebuffer)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint framebuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindFramebuffer(target, framebuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.framebuffer = framebuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(framebuffer);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBindFramebuffer);
+}
+
+void Debug_glBindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindRenderbuffer(target, renderbuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBindRenderbuffer);
+}
+
+void Debug_glBindTexture(GLenum target, GLuint texture)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindTexture(target, texture);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.texture = texture;
+
+    msg.set_arg0(target);
+    msg.set_arg1(texture);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBindTexture);
+}
+
+void Debug_glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLclampf red;
+        GLclampf green;
+        GLclampf blue;
+        GLclampf alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendColor(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(ToInt(red));
+    msg.set_arg1(ToInt(green));
+    msg.set_arg2(ToInt(blue));
+    msg.set_arg3(ToInt(alpha));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBlendColor);
+}
+
+void Debug_glBlendEquation( GLenum mode )
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendEquation(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBlendEquation);
+}
+
+void Debug_glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum modeRGB;
+        GLenum modeAlpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendEquationSeparate(modeRGB, modeAlpha);
+            return 0;
+        }
+    } caller;
+    caller.modeRGB = modeRGB;
+    caller.modeAlpha = modeAlpha;
+
+    msg.set_arg0(modeRGB);
+    msg.set_arg1(modeAlpha);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBlendEquationSeparate);
+}
+
+void Debug_glBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum sfactor;
+        GLenum dfactor;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendFunc(sfactor, dfactor);
+            return 0;
+        }
+    } caller;
+    caller.sfactor = sfactor;
+    caller.dfactor = dfactor;
+
+    msg.set_arg0(sfactor);
+    msg.set_arg1(dfactor);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBlendFunc);
+}
+
+void Debug_glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum srcRGB;
+        GLenum dstRGB;
+        GLenum srcAlpha;
+        GLenum dstAlpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+            return 0;
+        }
+    } caller;
+    caller.srcRGB = srcRGB;
+    caller.dstRGB = dstRGB;
+    caller.srcAlpha = srcAlpha;
+    caller.dstAlpha = dstAlpha;
+
+    msg.set_arg0(srcRGB);
+    msg.set_arg1(dstRGB);
+    msg.set_arg2(srcAlpha);
+    msg.set_arg3(dstAlpha);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBlendFuncSeparate);
+}
+
+void Debug_glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLsizeiptr size;
+        const GLvoid* data;
+        GLenum usage;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBufferData(target, size, data, usage);
+            getDbgContextThreadSpecific()->glBufferData(target, size, data, usage);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.size = size;
+    caller.data = data;
+    caller.usage = usage;
+
+    msg.set_arg0(target);
+    msg.set_arg1(size);
+    msg.set_arg2(ToInt(data));
+    msg.set_arg3(usage);
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(data), size * sizeof(char));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBufferData);
+}
+
+void Debug_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLintptr offset;
+        GLsizeiptr size;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBufferSubData(target, offset, size, data);
+            getDbgContextThreadSpecific()->glBufferSubData(target, offset, size, data);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.offset = offset;
+    caller.size = size;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(offset);
+    msg.set_arg2(size);
+    msg.set_arg3(ToInt(data));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(data), size * sizeof(char));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glBufferSubData);
+}
+
+GLenum Debug_glCheckFramebufferStatus(GLenum target)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCheckFramebufferStatus(target));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.target = target;
+
+    msg.set_arg0(target);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCheckFramebufferStatus);
+    return reinterpret_cast<GLenum>(ret);
+}
+
+void Debug_glClear(GLbitfield mask)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLbitfield mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClear(mask);
+            return 0;
+        }
+    } caller;
+    caller.mask = mask;
+
+    msg.set_arg0(mask);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glClear);
+}
+
+void Debug_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLclampf red;
+        GLclampf green;
+        GLclampf blue;
+        GLclampf alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearColor(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(ToInt(red));
+    msg.set_arg1(ToInt(green));
+    msg.set_arg2(ToInt(blue));
+    msg.set_arg3(ToInt(alpha));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glClearColor);
+}
+
+void Debug_glClearDepthf(GLclampf depth)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLclampf depth;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearDepthf(depth);
+            return 0;
+        }
+    } caller;
+    caller.depth = depth;
+
+    msg.set_arg0(ToInt(depth));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glClearDepthf);
+}
+
+void Debug_glClearStencil(GLint s)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint s;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearStencil(s);
+            return 0;
+        }
+    } caller;
+    caller.s = s;
+
+    msg.set_arg0(s);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glClearStencil);
+}
+
+void Debug_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLboolean red;
+        GLboolean green;
+        GLboolean blue;
+        GLboolean alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glColorMask(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(red);
+    msg.set_arg1(green);
+    msg.set_arg2(blue);
+    msg.set_arg3(alpha);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glColorMask);
+}
+
+void Debug_glCompileShader(GLuint shader)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompileShader(shader);
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCompileShader);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLenum internalformat;
+        GLsizei width;
+        GLsizei height;
+        GLint border;
+        GLsizei imageSize;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.internalformat = internalformat;
+    caller.width = width;
+    caller.height = height;
+    caller.border = border;
+    caller.imageSize = imageSize;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(internalformat);
+    msg.set_arg3(width);
+    msg.set_arg4(height);
+    msg.set_arg5(border);
+    msg.set_arg6(imageSize);
+    msg.set_arg7(ToInt(data));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCompressedTexImage2D);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint xoffset;
+        GLint yoffset;
+        GLsizei width;
+        GLsizei height;
+        GLenum format;
+        GLsizei imageSize;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.xoffset = xoffset;
+    caller.yoffset = yoffset;
+    caller.width = width;
+    caller.height = height;
+    caller.format = format;
+    caller.imageSize = imageSize;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(xoffset);
+    msg.set_arg3(yoffset);
+    msg.set_arg4(width);
+    msg.set_arg5(height);
+    msg.set_arg6(format);
+    msg.set_arg7(imageSize);
+    msg.set_arg8(ToInt(data));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCompressedTexSubImage2D);
+}
+
+void Debug_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLenum internalformat;
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+        GLint border;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+#ifdef EXTEND_AFTER_CALL_Debug_glCopyTexImage2D
+            EXTEND_AFTER_CALL_Debug_glCopyTexImage2D;
+#endif
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.internalformat = internalformat;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+    caller.border = border;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(internalformat);
+    msg.set_arg3(x);
+    msg.set_arg4(y);
+    msg.set_arg5(width);
+    msg.set_arg6(height);
+    msg.set_arg7(border);
+
+#ifdef EXTEND_Debug_glCopyTexImage2D
+    EXTEND_Debug_glCopyTexImage2D;
+#endif
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCopyTexImage2D);
+}
+
+void Debug_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint xoffset;
+        GLint yoffset;
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+#ifdef EXTEND_AFTER_CALL_Debug_glCopyTexSubImage2D
+            EXTEND_AFTER_CALL_Debug_glCopyTexSubImage2D;
+#endif
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.xoffset = xoffset;
+    caller.yoffset = yoffset;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(xoffset);
+    msg.set_arg3(yoffset);
+    msg.set_arg4(x);
+    msg.set_arg5(y);
+    msg.set_arg6(width);
+    msg.set_arg7(height);
+
+#ifdef EXTEND_Debug_glCopyTexSubImage2D
+    EXTEND_Debug_glCopyTexSubImage2D;
+#endif
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCopyTexSubImage2D);
+}
+
+GLuint Debug_glCreateProgram(void)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCreateProgram());
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCreateProgram);
+    return reinterpret_cast<GLuint>(ret);
+}
+
+GLuint Debug_glCreateShader(GLenum type)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum type;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCreateShader(type));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.type = type;
+
+    msg.set_arg0(type);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCreateShader);
+    return reinterpret_cast<GLuint>(ret);
+}
+
+void Debug_glCullFace(GLenum mode)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCullFace(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glCullFace);
+}
+
+void Debug_glDeleteBuffers(GLsizei n, const GLuint* buffers)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* buffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteBuffers(n, buffers);
+            getDbgContextThreadSpecific()->glDeleteBuffers(n, buffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.buffers = buffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(buffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(buffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDeleteBuffers);
+}
+
+void Debug_glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* framebuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteFramebuffers(n, framebuffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.framebuffers = framebuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(framebuffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(framebuffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDeleteFramebuffers);
+}
+
+void Debug_glDeleteProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDeleteProgram);
+}
+
+void Debug_glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* renderbuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteRenderbuffers(n, renderbuffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.renderbuffers = renderbuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(renderbuffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(renderbuffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDeleteRenderbuffers);
+}
+
+void Debug_glDeleteShader(GLuint shader)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteShader(shader);
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDeleteShader);
+}
+
+void Debug_glDeleteTextures(GLsizei n, const GLuint* textures)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* textures;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteTextures(n, textures);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.textures = textures;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(textures));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(textures), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDeleteTextures);
+}
+
+void Debug_glDepthFunc(GLenum func)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum func;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthFunc(func);
+            return 0;
+        }
+    } caller;
+    caller.func = func;
+
+    msg.set_arg0(func);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDepthFunc);
+}
+
+void Debug_glDepthMask(GLboolean flag)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLboolean flag;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthMask(flag);
+            return 0;
+        }
+    } caller;
+    caller.flag = flag;
+
+    msg.set_arg0(flag);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDepthMask);
+}
+
+void Debug_glDepthRangef(GLclampf zNear, GLclampf zFar)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLclampf zNear;
+        GLclampf zFar;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthRangef(zNear, zFar);
+            return 0;
+        }
+    } caller;
+    caller.zNear = zNear;
+    caller.zFar = zFar;
+
+    msg.set_arg0(ToInt(zNear));
+    msg.set_arg1(ToInt(zFar));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDepthRangef);
+}
+
+void Debug_glDetachShader(GLuint program, GLuint shader)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDetachShader(program, shader);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.shader = shader;
+
+    msg.set_arg0(program);
+    msg.set_arg1(shader);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDetachShader);
+}
+
+void Debug_glDisable(GLenum cap)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDisable(cap);
+            return 0;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDisable);
+}
+
+void Debug_glDisableVertexAttribArray(GLuint index)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint index;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDisableVertexAttribArray(index);
+            getDbgContextThreadSpecific()->glDisableVertexAttribArray(index);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+
+    msg.set_arg0(index);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glDisableVertexAttribArray);
+}
+
+void Debug_glEnable(GLenum cap)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glEnable(cap);
+            return 0;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glEnable);
+}
+
+void Debug_glEnableVertexAttribArray(GLuint index)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint index;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glEnableVertexAttribArray(index);
+            getDbgContextThreadSpecific()->glEnableVertexAttribArray(index);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+
+    msg.set_arg0(index);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glEnableVertexAttribArray);
+}
+
+void Debug_glFinish(void)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFinish();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glFinish);
+}
+
+void Debug_glFlush(void)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFlush();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glFlush);
+}
+
+void Debug_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum renderbuffertarget;
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.renderbuffertarget = renderbuffertarget;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(renderbuffertarget);
+    msg.set_arg3(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glFramebufferRenderbuffer);
+}
+
+void Debug_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum textarget;
+        GLuint texture;
+        GLint level;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFramebufferTexture2D(target, attachment, textarget, texture, level);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.textarget = textarget;
+    caller.texture = texture;
+    caller.level = level;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(textarget);
+    msg.set_arg3(texture);
+    msg.set_arg4(level);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glFramebufferTexture2D);
+}
+
+void Debug_glFrontFace(GLenum mode)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFrontFace(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glFrontFace);
+}
+
+void Debug_glGenBuffers(GLsizei n, GLuint* buffers)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* buffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenBuffers(n, buffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(buffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.buffers = buffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(buffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGenBuffers);
+}
+
+void Debug_glGenerateMipmap(GLenum target)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGenerateMipmap(target);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+
+    msg.set_arg0(target);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGenerateMipmap);
+}
+
+void Debug_glGenFramebuffers(GLsizei n, GLuint* framebuffers)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* framebuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenFramebuffers(n, framebuffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(framebuffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.framebuffers = framebuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(framebuffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGenFramebuffers);
+}
+
+void Debug_glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* renderbuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenRenderbuffers(n, renderbuffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(renderbuffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.renderbuffers = renderbuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(renderbuffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGenRenderbuffers);
+}
+
+void Debug_glGenTextures(GLsizei n, GLuint* textures)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* textures;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenTextures(n, textures);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(textures), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.textures = textures;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(textures));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGenTextures);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLint* size;
+        GLenum* type;
+        GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetActiveAttrib(program, index, bufsize, length, size, type, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.size = size;
+    caller.type = type;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(bufsize);
+    msg.set_arg3(ToInt(length));
+    msg.set_arg4(ToInt(size));
+    msg.set_arg5(ToInt(type));
+    msg.set_arg6(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetActiveAttrib);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLint* size;
+        GLenum* type;
+        GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetActiveUniform(program, index, bufsize, length, size, type, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.size = size;
+    caller.type = type;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(bufsize);
+    msg.set_arg3(ToInt(length));
+    msg.set_arg4(ToInt(size));
+    msg.set_arg5(ToInt(type));
+    msg.set_arg6(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetActiveUniform);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLsizei maxcount;
+        GLsizei* count;
+        GLuint* shaders;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetAttachedShaders(program, maxcount, count, shaders);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.maxcount = maxcount;
+    caller.count = count;
+    caller.shaders = shaders;
+
+    msg.set_arg0(program);
+    msg.set_arg1(maxcount);
+    msg.set_arg2(ToInt(count));
+    msg.set_arg3(ToInt(shaders));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetAttachedShaders);
+}
+
+int Debug_glGetAttribLocation(GLuint program, const GLchar* name)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetAttribLocation(program, name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetAttribLocation);
+    return reinterpret_cast<int>(ret);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetBooleanv(GLenum pname, GLboolean* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLboolean* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetBooleanv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetBooleanv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetBufferParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetBufferParameteriv);
+}
+
+GLenum Debug_glGetError(void)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetError());
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetError);
+    return reinterpret_cast<GLenum>(ret);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetFloatv(GLenum pname, GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetFloatv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetFloatv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(pname);
+    msg.set_arg3(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetFramebufferAttachmentParameteriv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetIntegerv(GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetIntegerv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetIntegerv);
+}
+
+void Debug_glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetProgramiv(program, pname, params);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(params), 1 * sizeof(GLint));
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetProgramiv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* infolog;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetProgramInfoLog(program, bufsize, length, infolog);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(infolog), strlen(infolog) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.infolog = infolog;
+
+    msg.set_arg0(program);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(infolog));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetProgramInfoLog);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetRenderbufferParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetRenderbufferParameteriv);
+}
+
+void Debug_glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderiv(shader, pname, params);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(params), 1 * sizeof(GLint));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetShaderiv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* infolog;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderInfoLog(shader, bufsize, length, infolog);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(infolog), strlen(infolog) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.infolog = infolog;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(infolog));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetShaderInfoLog);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum shadertype;
+        GLenum precisiontype;
+        GLint* range;
+        GLint* precision;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+            return 0;
+        }
+    } caller;
+    caller.shadertype = shadertype;
+    caller.precisiontype = precisiontype;
+    caller.range = range;
+    caller.precision = precision;
+
+    msg.set_arg0(shadertype);
+    msg.set_arg1(precisiontype);
+    msg.set_arg2(ToInt(range));
+    msg.set_arg3(ToInt(precision));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetShaderPrecisionFormat);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* source;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderSource(shader, bufsize, length, source);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(source), strlen(source) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.source = source;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(source));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetShaderSource);
+}
+
+// FIXME: this function has pointers, it should be hand written
+const GLubyte* Debug_glGetString(GLenum name)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetString(name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.name = name;
+
+    msg.set_arg0(name);
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetString);
+    return reinterpret_cast<const GLubyte*>(ret);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetTexParameterfv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetTexParameterfv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetTexParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetTexParameteriv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLint location;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetUniformfv(program, location, params);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.location = location;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(location);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetUniformfv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetUniformiv(GLuint program, GLint location, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        GLint location;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetUniformiv(program, location, params);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.location = location;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(location);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetUniformiv);
+}
+
+int Debug_glGetUniformLocation(GLuint program, const GLchar* name)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetUniformLocation(program, name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetUniformLocation);
+    return reinterpret_cast<int>(ret);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribfv(index, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetVertexAttribfv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribiv(index, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetVertexAttribiv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLvoid** pointer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribPointerv(index, pname, pointer);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.pointer = pointer;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(pointer));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glGetVertexAttribPointerv);
+}
+
+void Debug_glHint(GLenum target, GLenum mode)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glHint(target, mode);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.mode = mode;
+
+    msg.set_arg0(target);
+    msg.set_arg1(mode);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glHint);
+}
+
+GLboolean Debug_glIsBuffer(GLuint buffer)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint buffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsBuffer(buffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.buffer = buffer;
+
+    msg.set_arg0(buffer);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glIsBuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsEnabled(GLenum cap)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsEnabled(cap));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glIsEnabled);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsFramebuffer(GLuint framebuffer)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint framebuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsFramebuffer(framebuffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.framebuffer = framebuffer;
+
+    msg.set_arg0(framebuffer);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glIsFramebuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsProgram(program));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glIsProgram);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsRenderbuffer(GLuint renderbuffer)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsRenderbuffer(renderbuffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glIsRenderbuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsShader(GLuint shader)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsShader(shader));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glIsShader);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsTexture(GLuint texture)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsTexture(texture));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.texture = texture;
+
+    msg.set_arg0(texture);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glIsTexture);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+void Debug_glLineWidth(GLfloat width)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLfloat width;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glLineWidth(width);
+            return 0;
+        }
+    } caller;
+    caller.width = width;
+
+    msg.set_arg0(ToInt(width));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glLineWidth);
+}
+
+void Debug_glLinkProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glLinkProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glLinkProgram);
+}
+
+void Debug_glPixelStorei(GLenum pname, GLint param)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLint param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glPixelStorei(pname, param);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(param);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glPixelStorei);
+}
+
+void Debug_glPolygonOffset(GLfloat factor, GLfloat units)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLfloat factor;
+        GLfloat units;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glPolygonOffset(factor, units);
+            return 0;
+        }
+    } caller;
+    caller.factor = factor;
+    caller.units = units;
+
+    msg.set_arg0(ToInt(factor));
+    msg.set_arg1(ToInt(units));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glPolygonOffset);
+}
+
+void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+        GLenum format;
+        GLenum type;
+        GLvoid* pixels;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glReadPixels(x, y, width, height, format, type, pixels);
+#ifdef EXTEND_AFTER_CALL_Debug_glReadPixels
+            EXTEND_AFTER_CALL_Debug_glReadPixels;
+#endif
+            return 0;
+        }
+    } caller;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+    caller.format = format;
+    caller.type = type;
+    caller.pixels = pixels;
+
+    msg.set_arg0(x);
+    msg.set_arg1(y);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+    msg.set_arg4(format);
+    msg.set_arg5(type);
+    msg.set_arg6(ToInt(pixels));
+
+    // FIXME: check for pointer usage
+#ifdef EXTEND_Debug_glReadPixels
+    EXTEND_Debug_glReadPixels;
+#endif
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glReadPixels);
+}
+
+void Debug_glReleaseShaderCompiler(void)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glReleaseShaderCompiler();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glReleaseShaderCompiler);
+}
+
+void Debug_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum internalformat;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glRenderbufferStorage(target, internalformat, width, height);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.internalformat = internalformat;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(target);
+    msg.set_arg1(internalformat);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glRenderbufferStorage);
+}
+
+void Debug_glSampleCoverage(GLclampf value, GLboolean invert)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLclampf value;
+        GLboolean invert;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glSampleCoverage(value, invert);
+            return 0;
+        }
+    } caller;
+    caller.value = value;
+    caller.invert = invert;
+
+    msg.set_arg0(ToInt(value));
+    msg.set_arg1(invert);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glSampleCoverage);
+}
+
+void Debug_glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glScissor(x, y, width, height);
+            return 0;
+        }
+    } caller;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(x);
+    msg.set_arg1(y);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glScissor);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* shaders;
+        GLenum binaryformat;
+        const GLvoid* binary;
+        GLsizei length;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glShaderBinary(n, shaders, binaryformat, binary, length);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.shaders = shaders;
+    caller.binaryformat = binaryformat;
+    caller.binary = binary;
+    caller.length = length;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(shaders));
+    msg.set_arg2(binaryformat);
+    msg.set_arg3(ToInt(binary));
+    msg.set_arg4(length);
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glShaderBinary);
+}
+
+void Debug_glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLsizei count;
+        const GLchar** string;
+        const GLint* length;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glShaderSource(shader, count, string, length);
+#ifdef EXTEND_AFTER_CALL_Debug_glShaderSource
+            EXTEND_AFTER_CALL_Debug_glShaderSource;
+#endif
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.count = count;
+    caller.string = string;
+    caller.length = length;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(string));
+    msg.set_arg3(ToInt(length));
+
+    // FIXME: check for pointer usage
+#ifdef EXTEND_Debug_glShaderSource
+    EXTEND_Debug_glShaderSource;
+#endif
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glShaderSource);
+}
+
+void Debug_glStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum func;
+        GLint ref;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilFunc(func, ref, mask);
+            return 0;
+        }
+    } caller;
+    caller.func = func;
+    caller.ref = ref;
+    caller.mask = mask;
+
+    msg.set_arg0(func);
+    msg.set_arg1(ref);
+    msg.set_arg2(mask);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glStencilFunc);
+}
+
+void Debug_glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum face;
+        GLenum func;
+        GLint ref;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilFuncSeparate(face, func, ref, mask);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.func = func;
+    caller.ref = ref;
+    caller.mask = mask;
+
+    msg.set_arg0(face);
+    msg.set_arg1(func);
+    msg.set_arg2(ref);
+    msg.set_arg3(mask);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glStencilFuncSeparate);
+}
+
+void Debug_glStencilMask(GLuint mask)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilMask(mask);
+            return 0;
+        }
+    } caller;
+    caller.mask = mask;
+
+    msg.set_arg0(mask);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glStencilMask);
+}
+
+void Debug_glStencilMaskSeparate(GLenum face, GLuint mask)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum face;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilMaskSeparate(face, mask);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.mask = mask;
+
+    msg.set_arg0(face);
+    msg.set_arg1(mask);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glStencilMaskSeparate);
+}
+
+void Debug_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum fail;
+        GLenum zfail;
+        GLenum zpass;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilOp(fail, zfail, zpass);
+            return 0;
+        }
+    } caller;
+    caller.fail = fail;
+    caller.zfail = zfail;
+    caller.zpass = zpass;
+
+    msg.set_arg0(fail);
+    msg.set_arg1(zfail);
+    msg.set_arg2(zpass);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glStencilOp);
+}
+
+void Debug_glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum face;
+        GLenum fail;
+        GLenum zfail;
+        GLenum zpass;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilOpSeparate(face, fail, zfail, zpass);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.fail = fail;
+    caller.zfail = zfail;
+    caller.zpass = zpass;
+
+    msg.set_arg0(face);
+    msg.set_arg1(fail);
+    msg.set_arg2(zfail);
+    msg.set_arg3(zpass);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glStencilOpSeparate);
+}
+
+void Debug_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint internalformat;
+        GLsizei width;
+        GLsizei height;
+        GLint border;
+        GLenum format;
+        GLenum type;
+        const GLvoid* pixels;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+#ifdef EXTEND_AFTER_CALL_Debug_glTexImage2D
+            EXTEND_AFTER_CALL_Debug_glTexImage2D;
+#endif
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.internalformat = internalformat;
+    caller.width = width;
+    caller.height = height;
+    caller.border = border;
+    caller.format = format;
+    caller.type = type;
+    caller.pixels = pixels;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(internalformat);
+    msg.set_arg3(width);
+    msg.set_arg4(height);
+    msg.set_arg5(border);
+    msg.set_arg6(format);
+    msg.set_arg7(type);
+    msg.set_arg8(ToInt(pixels));
+
+    // FIXME: check for pointer usage
+#ifdef EXTEND_Debug_glTexImage2D
+    EXTEND_Debug_glTexImage2D;
+#endif
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glTexImage2D);
+}
+
+void Debug_glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLfloat param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameterf(target, pname, param);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(param));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glTexParameterf);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        const GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameterfv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glTexParameterfv);
+}
+
+void Debug_glTexParameteri(GLenum target, GLenum pname, GLint param)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameteri(target, pname, param);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(param);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glTexParameteri);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        const GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glTexParameteriv);
+}
+
+void Debug_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint xoffset;
+        GLint yoffset;
+        GLsizei width;
+        GLsizei height;
+        GLenum format;
+        GLenum type;
+        const GLvoid* pixels;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+#ifdef EXTEND_AFTER_CALL_Debug_glTexSubImage2D
+            EXTEND_AFTER_CALL_Debug_glTexSubImage2D;
+#endif
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.xoffset = xoffset;
+    caller.yoffset = yoffset;
+    caller.width = width;
+    caller.height = height;
+    caller.format = format;
+    caller.type = type;
+    caller.pixels = pixels;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(xoffset);
+    msg.set_arg3(yoffset);
+    msg.set_arg4(width);
+    msg.set_arg5(height);
+    msg.set_arg6(format);
+    msg.set_arg7(type);
+    msg.set_arg8(ToInt(pixels));
+
+    // FIXME: check for pointer usage
+#ifdef EXTEND_Debug_glTexSubImage2D
+    EXTEND_Debug_glTexSubImage2D;
+#endif
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glTexSubImage2D);
+}
+
+void Debug_glUniform1f(GLint location, GLfloat x)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1f(location, x);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform1f);
+}
+
+void Debug_glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 1*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform1fv);
+}
+
+void Debug_glUniform1i(GLint location, GLint x)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1i(location, x);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform1i);
+}
+
+void Debug_glUniform1iv(GLint location, GLsizei count, const GLint* v)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 1*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform1iv);
+}
+
+void Debug_glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2f(location, x, y);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform2f);
+}
+
+void Debug_glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 2*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform2fv);
+}
+
+void Debug_glUniform2i(GLint location, GLint x, GLint y)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2i(location, x, y);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform2i);
+}
+
+void Debug_glUniform2iv(GLint location, GLsizei count, const GLint* v)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 2*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform2iv);
+}
+
+void Debug_glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3f(location, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform3f);
+}
+
+void Debug_glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 3*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform3fv);
+}
+
+void Debug_glUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+        GLint z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3i(location, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+    msg.set_arg3(z);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform3i);
+}
+
+void Debug_glUniform3iv(GLint location, GLsizei count, const GLint* v)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 3*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform3iv);
+}
+
+void Debug_glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+        GLfloat w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4f(location, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+    msg.set_arg4(ToInt(w));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform4f);
+}
+
+void Debug_glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 4*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform4fv);
+}
+
+void Debug_glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+        GLint z;
+        GLint w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4i(location, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+    msg.set_arg3(z);
+    msg.set_arg4(w);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform4i);
+}
+
+void Debug_glUniform4iv(GLint location, GLsizei count, const GLint* v)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 4*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniform4iv);
+}
+
+void Debug_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix2fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 4*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniformMatrix2fv);
+}
+
+void Debug_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix3fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 9*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniformMatrix3fv);
+}
+
+void Debug_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix4fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 16*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUniformMatrix4fv);
+}
+
+void Debug_glUseProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUseProgram(program);
+            getDbgContextThreadSpecific()->glUseProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glUseProgram);
+}
+
+void Debug_glValidateProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glValidateProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glValidateProgram);
+}
+
+void Debug_glVertexAttrib1f(GLuint indx, GLfloat x)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib1f(indx, x);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttrib1f);
+}
+
+void Debug_glVertexAttrib1fv(GLuint indx, const GLfloat* values)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib1fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 1 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttrib1fv);
+}
+
+void Debug_glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib2f(indx, x, y);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttrib2f);
+}
+
+void Debug_glVertexAttrib2fv(GLuint indx, const GLfloat* values)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib2fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 2 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttrib2fv);
+}
+
+void Debug_glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib3f(indx, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttrib3f);
+}
+
+void Debug_glVertexAttrib3fv(GLuint indx, const GLfloat* values)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib3fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 3 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttrib3fv);
+}
+
+void Debug_glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+        GLfloat w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib4f(indx, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+    msg.set_arg4(ToInt(w));
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttrib4f);
+}
+
+void Debug_glVertexAttrib4fv(GLuint indx, const GLfloat* values)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib4fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 4 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttrib4fv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLint size;
+        GLenum type;
+        GLboolean normalized;
+        GLsizei stride;
+        const GLvoid* ptr;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+            getDbgContextThreadSpecific()->glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.size = size;
+    caller.type = type;
+    caller.normalized = normalized;
+    caller.stride = stride;
+    caller.ptr = ptr;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(size);
+    msg.set_arg2(type);
+    msg.set_arg3(normalized);
+    msg.set_arg4(stride);
+    msg.set_arg5(ToInt(ptr));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glVertexAttribPointer);
+}
+
+void Debug_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glViewport(x, y, width, height);
+            return 0;
+        }
+    } caller;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(x);
+    msg.set_arg1(y);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_glViewport);
+}
+
+// FIXME: the following functions should be written by hand
+void Debug_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+void Debug_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+void Debug_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+void Debug_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+void Debug_glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+void Debug_glGetBooleanv(GLenum pname, GLboolean* params);
+void Debug_glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
+void Debug_glGetFloatv(GLenum pname, GLfloat* params);
+void Debug_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
+void Debug_glGetIntegerv(GLenum pname, GLint* params);
+void Debug_glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+void Debug_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params);
+void Debug_glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+void Debug_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+void Debug_glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+const GLubyte* Debug_glGetString(GLenum name);
+void Debug_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
+void Debug_glGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
+void Debug_glGetUniformfv(GLuint program, GLint location, GLfloat* params);
+void Debug_glGetUniformiv(GLuint program, GLint location, GLint* params);
+void Debug_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
+void Debug_glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
+void Debug_glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer);
+void Debug_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+void Debug_glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
+void Debug_glTexParameteriv(GLenum target, GLenum pname, const GLint* params);
+void Debug_glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
diff --git a/opengl/libs/GLES2_dbg/src/api.h b/opengl/libs/GLES2_dbg/src/api.h
new file mode 100644
index 0000000..0b227bc
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/api.h
@@ -0,0 +1,58 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#define EXTEND_Debug_glCopyTexImage2D \
+    DbgContext * const dbg = getDbgContextThreadSpecific(); \
+    void * readData = dbg->GetReadPixelsBuffer(4 * width * height); \
+    /* pick easy format for client to convert */ \
+    dbg->hooks->gl.glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, readData); \
+    dbg->CompressReadPixelBuffer(msg.mutable_data()); \
+    msg.set_data_type(msg.ReferencedImage); \
+    msg.set_pixel_format(GL_RGBA); \
+    msg.set_pixel_type(GL_UNSIGNED_BYTE);
+
+#define EXTEND_Debug_glCopyTexSubImage2D EXTEND_Debug_glCopyTexImage2D
+
+#define EXTEND_AFTER_CALL_Debug_glReadPixels \
+    { \
+        DbgContext * const dbg = getDbgContextThreadSpecific(); \
+        if (dbg->IsReadPixelBuffer(pixels)) { \
+            dbg->CompressReadPixelBuffer(msg.mutable_data()); \
+            msg.set_data_type(msg.ReferencedImage); \
+        } else { \
+            const unsigned int size = width * height * GetBytesPerPixel(format, type); \
+            dbg->Compress(pixels, size, msg.mutable_data()); \
+            msg.set_data_type(msg.NonreferencedImage); \
+        } \
+    }
+
+#define EXTEND_Debug_glShaderSource \
+    std::string * const data = msg.mutable_data(); \
+    for (unsigned i = 0; i < count; i++) \
+        if (!length || length[i] < 0) \
+            data->append(string[i]); \
+        else \
+            data->append(string[i], length[i]);
+
+#define EXTEND_Debug_glTexImage2D \
+    if (pixels) { \
+        DbgContext * const dbg = getDbgContextThreadSpecific(); \
+        const unsigned size = GetBytesPerPixel(format, type) * width * height; \
+        assert(0 < size); \
+        dbg->Compress(pixels, size, msg.mutable_data()); \
+    }
+
+#define EXTEND_Debug_glTexSubImage2D EXTEND_Debug_glTexImage2D
diff --git a/opengl/libs/GLES2_dbg/src/caller.cpp b/opengl/libs/GLES2_dbg/src/caller.cpp
new file mode 100644
index 0000000..6b72751
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/caller.cpp
@@ -0,0 +1,778 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+// auto generated by generate_caller_cpp.py
+// implement declarations in caller.h
+
+#include "header.h"
+
+namespace android {
+
+static const int * GenerateCall_glCompressedTexImage2D(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glCompressedTexSubImage2D(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glDrawElements(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGenBuffers(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGenFramebuffers(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGenRenderbuffers(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGenTextures(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetActiveAttrib(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetActiveUniform(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetAttachedShaders(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetBooleanv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetBufferParameteriv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetFloatv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetFramebufferAttachmentParameteriv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetIntegerv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetProgramiv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetProgramInfoLog(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetRenderbufferParameteriv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetShaderiv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetShaderInfoLog(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetShaderPrecisionFormat(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetShaderSource(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetString(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetTexParameterfv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetTexParameteriv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetUniformfv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetUniformiv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetVertexAttribfv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetVertexAttribiv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glGetVertexAttribPointerv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glReadPixels(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glShaderBinary(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glShaderSource(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glTexImage2D(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glTexParameterfv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glTexParameteriv(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glTexSubImage2D(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+static const int * GenerateCall_glVertexAttribPointer(DbgContext * const dbg,
+    const glesv2debugger::Message & cmd, glesv2debugger::Message & msg, const int * const prevRet);
+
+#include "caller.h"
+
+const int * GenerateCall(DbgContext * const dbg, const glesv2debugger::Message & cmd,
+                  glesv2debugger::Message & msg, const int * const prevRet)
+{
+    LOGD("GenerateCall function=%u", cmd.function());
+    const int * ret = prevRet; // only some functions have return value
+    nsecs_t c0 = systemTime(timeMode);
+    switch (cmd.function()) {    case glesv2debugger::Message_Function_glActiveTexture:
+        dbg->hooks->gl.glActiveTexture(
+            static_cast<GLenum>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glAttachShader:
+        dbg->hooks->gl.glAttachShader(
+            static_cast<GLuint>(cmd.arg0()), static_cast<GLuint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBindAttribLocation:
+        dbg->hooks->gl.glBindAttribLocation(
+            static_cast<GLuint>(cmd.arg0()), static_cast<GLuint>(cmd.arg1()), 
+            reinterpret_cast<GLchar*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glBindBuffer:
+        dbg->hooks->gl.glBindBuffer(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLuint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBindFramebuffer:
+        dbg->hooks->gl.glBindFramebuffer(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLuint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBindRenderbuffer:
+        dbg->hooks->gl.glBindRenderbuffer(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLuint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBindTexture:
+        dbg->hooks->gl.glBindTexture(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLuint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBlendColor:
+        dbg->hooks->gl.glBlendColor(
+            static_cast<GLclampf>(cmd.arg0()), static_cast<GLclampf>(cmd.arg1()), 
+            static_cast<GLclampf>(cmd.arg2()), static_cast<GLclampf>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBlendEquation:
+        dbg->hooks->gl.glBlendEquation(
+            static_cast<GLenum>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glBlendEquationSeparate:
+        dbg->hooks->gl.glBlendEquationSeparate(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBlendFunc:
+        dbg->hooks->gl.glBlendFunc(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBlendFuncSeparate:
+        dbg->hooks->gl.glBlendFuncSeparate(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLenum>(cmd.arg2()), static_cast<GLenum>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glBufferData:
+        dbg->hooks->gl.glBufferData(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLsizeiptr>(cmd.arg1()), 
+            reinterpret_cast<GLvoid*>(const_cast<char *>(cmd.data().data())), 
+            static_cast<GLenum>(cmd.arg3()));
+        break;
+    case glesv2debugger::Message_Function_glBufferSubData:
+        dbg->hooks->gl.glBufferSubData(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLintptr>(cmd.arg1()), 
+            static_cast<GLsizeiptr>(cmd.arg2()), reinterpret_cast<GLvoid*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glCheckFramebufferStatus:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glCheckFramebufferStatus(
+            static_cast<GLenum>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glClear:
+        dbg->hooks->gl.glClear(
+            static_cast<GLbitfield>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glClearColor:
+        dbg->hooks->gl.glClearColor(
+            static_cast<GLclampf>(cmd.arg0()), static_cast<GLclampf>(cmd.arg1()), 
+            static_cast<GLclampf>(cmd.arg2()), static_cast<GLclampf>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glClearDepthf:
+        dbg->hooks->gl.glClearDepthf(
+            static_cast<GLclampf>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glClearStencil:
+        dbg->hooks->gl.glClearStencil(
+            static_cast<GLint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glColorMask:
+        dbg->hooks->gl.glColorMask(
+            GLboolean(cmd.arg0()), GLboolean(cmd.arg1()), GLboolean(cmd.arg2()), 
+            GLboolean(cmd.arg3()));
+        break;
+    case glesv2debugger::Message_Function_glCompileShader:
+        dbg->hooks->gl.glCompileShader(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glCompressedTexImage2D:
+        ret = GenerateCall_glCompressedTexImage2D(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glCompressedTexSubImage2D:
+        ret = GenerateCall_glCompressedTexSubImage2D(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glCopyTexImage2D:
+        dbg->hooks->gl.glCopyTexImage2D(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLenum>(cmd.arg2()), static_cast<GLint>(cmd.arg3()), 
+            static_cast<GLint>(cmd.arg4()), static_cast<GLsizei>(cmd.arg5()), 
+            static_cast<GLsizei>(cmd.arg6()), static_cast<GLint>(cmd.arg7())
+            );
+        break;
+    case glesv2debugger::Message_Function_glCopyTexSubImage2D:
+        dbg->hooks->gl.glCopyTexSubImage2D(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLint>(cmd.arg2()), static_cast<GLint>(cmd.arg3()), 
+            static_cast<GLint>(cmd.arg4()), static_cast<GLint>(cmd.arg5()), 
+            static_cast<GLsizei>(cmd.arg6()), static_cast<GLsizei>(cmd.arg7())
+            );
+        break;
+    case glesv2debugger::Message_Function_glCreateProgram:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glCreateProgram(
+            )));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glCreateShader:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glCreateShader(
+            static_cast<GLenum>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glCullFace:
+        dbg->hooks->gl.glCullFace(
+            static_cast<GLenum>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glDeleteBuffers:
+        dbg->hooks->gl.glDeleteBuffers(
+            static_cast<GLsizei>(cmd.arg0()), reinterpret_cast<GLuint*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glDeleteFramebuffers:
+        dbg->hooks->gl.glDeleteFramebuffers(
+            static_cast<GLsizei>(cmd.arg0()), reinterpret_cast<GLuint*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glDeleteProgram:
+        dbg->hooks->gl.glDeleteProgram(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glDeleteRenderbuffers:
+        dbg->hooks->gl.glDeleteRenderbuffers(
+            static_cast<GLsizei>(cmd.arg0()), reinterpret_cast<GLuint*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glDeleteShader:
+        dbg->hooks->gl.glDeleteShader(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glDeleteTextures:
+        dbg->hooks->gl.glDeleteTextures(
+            static_cast<GLsizei>(cmd.arg0()), reinterpret_cast<GLuint*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glDepthFunc:
+        dbg->hooks->gl.glDepthFunc(
+            static_cast<GLenum>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glDepthMask:
+        dbg->hooks->gl.glDepthMask(
+            GLboolean(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glDepthRangef:
+        dbg->hooks->gl.glDepthRangef(
+            static_cast<GLclampf>(cmd.arg0()), static_cast<GLclampf>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glDetachShader:
+        dbg->hooks->gl.glDetachShader(
+            static_cast<GLuint>(cmd.arg0()), static_cast<GLuint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glDisable:
+        dbg->hooks->gl.glDisable(
+            static_cast<GLenum>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glDisableVertexAttribArray:
+        dbg->hooks->gl.glDisableVertexAttribArray(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glDrawArrays:
+        dbg->hooks->gl.glDrawArrays(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLsizei>(cmd.arg2()));
+        break;
+    case glesv2debugger::Message_Function_glDrawElements:
+        ret = GenerateCall_glDrawElements(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glEnable:
+        dbg->hooks->gl.glEnable(
+            static_cast<GLenum>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glEnableVertexAttribArray:
+        dbg->hooks->gl.glEnableVertexAttribArray(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glFinish:
+        dbg->hooks->gl.glFinish(
+            );
+        break;
+    case glesv2debugger::Message_Function_glFlush:
+        dbg->hooks->gl.glFlush(
+            );
+        break;
+    case glesv2debugger::Message_Function_glFramebufferRenderbuffer:
+        dbg->hooks->gl.glFramebufferRenderbuffer(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLenum>(cmd.arg2()), static_cast<GLuint>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glFramebufferTexture2D:
+        dbg->hooks->gl.glFramebufferTexture2D(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLenum>(cmd.arg2()), static_cast<GLuint>(cmd.arg3()), 
+            static_cast<GLint>(cmd.arg4()));
+        break;
+    case glesv2debugger::Message_Function_glFrontFace:
+        dbg->hooks->gl.glFrontFace(
+            static_cast<GLenum>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glGenBuffers:
+        ret = GenerateCall_glGenBuffers(dbg, cmd, msg, prevRet);
+        break; // annotated output pointers
+    case glesv2debugger::Message_Function_glGenerateMipmap:
+        dbg->hooks->gl.glGenerateMipmap(
+            static_cast<GLenum>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glGenFramebuffers:
+        ret = GenerateCall_glGenFramebuffers(dbg, cmd, msg, prevRet);
+        break; // annotated output pointers
+    case glesv2debugger::Message_Function_glGenRenderbuffers:
+        ret = GenerateCall_glGenRenderbuffers(dbg, cmd, msg, prevRet);
+        break; // annotated output pointers
+    case glesv2debugger::Message_Function_glGenTextures:
+        ret = GenerateCall_glGenTextures(dbg, cmd, msg, prevRet);
+        break; // annotated output pointers
+    case glesv2debugger::Message_Function_glGetActiveAttrib:
+        ret = GenerateCall_glGetActiveAttrib(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetActiveUniform:
+        ret = GenerateCall_glGetActiveUniform(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetAttachedShaders:
+        ret = GenerateCall_glGetAttachedShaders(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetAttribLocation:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glGetAttribLocation(
+            static_cast<GLuint>(cmd.arg0()), reinterpret_cast<GLchar*>(const_cast<char *>(cmd.data().data()))
+            )));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glGetBooleanv:
+        ret = GenerateCall_glGetBooleanv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetBufferParameteriv:
+        ret = GenerateCall_glGetBufferParameteriv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetError:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glGetError(
+            )));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glGetFloatv:
+        ret = GenerateCall_glGetFloatv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetFramebufferAttachmentParameteriv:
+        ret = GenerateCall_glGetFramebufferAttachmentParameteriv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetIntegerv:
+        ret = GenerateCall_glGetIntegerv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetProgramiv:
+        ret = GenerateCall_glGetProgramiv(dbg, cmd, msg, prevRet);
+        break; // annotated output pointers
+    case glesv2debugger::Message_Function_glGetProgramInfoLog:
+        ret = GenerateCall_glGetProgramInfoLog(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetRenderbufferParameteriv:
+        ret = GenerateCall_glGetRenderbufferParameteriv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetShaderiv:
+        ret = GenerateCall_glGetShaderiv(dbg, cmd, msg, prevRet);
+        break; // annotated output pointers
+    case glesv2debugger::Message_Function_glGetShaderInfoLog:
+        ret = GenerateCall_glGetShaderInfoLog(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetShaderPrecisionFormat:
+        ret = GenerateCall_glGetShaderPrecisionFormat(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetShaderSource:
+        ret = GenerateCall_glGetShaderSource(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetString:
+        ret = GenerateCall_glGetString(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetTexParameterfv:
+        ret = GenerateCall_glGetTexParameterfv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetTexParameteriv:
+        ret = GenerateCall_glGetTexParameteriv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetUniformfv:
+        ret = GenerateCall_glGetUniformfv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetUniformiv:
+        ret = GenerateCall_glGetUniformiv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetUniformLocation:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glGetUniformLocation(
+            static_cast<GLuint>(cmd.arg0()), reinterpret_cast<GLchar*>(const_cast<char *>(cmd.data().data()))
+            )));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glGetVertexAttribfv:
+        ret = GenerateCall_glGetVertexAttribfv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetVertexAttribiv:
+        ret = GenerateCall_glGetVertexAttribiv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glGetVertexAttribPointerv:
+        ret = GenerateCall_glGetVertexAttribPointerv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glHint:
+        dbg->hooks->gl.glHint(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glIsBuffer:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glIsBuffer(
+            static_cast<GLuint>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glIsEnabled:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glIsEnabled(
+            static_cast<GLenum>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glIsFramebuffer:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glIsFramebuffer(
+            static_cast<GLuint>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glIsProgram:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glIsProgram(
+            static_cast<GLuint>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glIsRenderbuffer:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glIsRenderbuffer(
+            static_cast<GLuint>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glIsShader:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glIsShader(
+            static_cast<GLuint>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glIsTexture:
+        msg.set_ret(static_cast<int>(dbg->hooks->gl.glIsTexture(
+            static_cast<GLuint>(cmd.arg0()))));
+        if (cmd.has_ret())
+            ret = reinterpret_cast<int *>(msg.ret());
+        break;
+    case glesv2debugger::Message_Function_glLineWidth:
+        dbg->hooks->gl.glLineWidth(
+            static_cast<GLfloat>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glLinkProgram:
+        dbg->hooks->gl.glLinkProgram(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glPixelStorei:
+        dbg->hooks->gl.glPixelStorei(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glPolygonOffset:
+        dbg->hooks->gl.glPolygonOffset(
+            static_cast<GLfloat>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glReadPixels:
+        ret = GenerateCall_glReadPixels(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glReleaseShaderCompiler:
+        dbg->hooks->gl.glReleaseShaderCompiler(
+            );
+        break;
+    case glesv2debugger::Message_Function_glRenderbufferStorage:
+        dbg->hooks->gl.glRenderbufferStorage(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLsizei>(cmd.arg2()), static_cast<GLsizei>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glSampleCoverage:
+        dbg->hooks->gl.glSampleCoverage(
+            static_cast<GLclampf>(cmd.arg0()), GLboolean(cmd.arg1()));
+        break;
+    case glesv2debugger::Message_Function_glScissor:
+        dbg->hooks->gl.glScissor(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLsizei>(cmd.arg2()), static_cast<GLsizei>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glShaderBinary:
+        ret = GenerateCall_glShaderBinary(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glShaderSource:
+        ret = GenerateCall_glShaderSource(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glStencilFunc:
+        dbg->hooks->gl.glStencilFunc(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLuint>(cmd.arg2()));
+        break;
+    case glesv2debugger::Message_Function_glStencilFuncSeparate:
+        dbg->hooks->gl.glStencilFuncSeparate(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLint>(cmd.arg2()), static_cast<GLuint>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glStencilMask:
+        dbg->hooks->gl.glStencilMask(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glStencilMaskSeparate:
+        dbg->hooks->gl.glStencilMaskSeparate(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLuint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glStencilOp:
+        dbg->hooks->gl.glStencilOp(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLenum>(cmd.arg2()));
+        break;
+    case glesv2debugger::Message_Function_glStencilOpSeparate:
+        dbg->hooks->gl.glStencilOpSeparate(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLenum>(cmd.arg2()), static_cast<GLenum>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glTexImage2D:
+        ret = GenerateCall_glTexImage2D(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glTexParameterf:
+        dbg->hooks->gl.glTexParameterf(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLfloat>(cmd.arg2()));
+        break;
+    case glesv2debugger::Message_Function_glTexParameterfv:
+        ret = GenerateCall_glTexParameterfv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glTexParameteri:
+        dbg->hooks->gl.glTexParameteri(
+            static_cast<GLenum>(cmd.arg0()), static_cast<GLenum>(cmd.arg1()), 
+            static_cast<GLint>(cmd.arg2()));
+        break;
+    case glesv2debugger::Message_Function_glTexParameteriv:
+        ret = GenerateCall_glTexParameteriv(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glTexSubImage2D:
+        ret = GenerateCall_glTexSubImage2D(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glUniform1f:
+        dbg->hooks->gl.glUniform1f(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform1fv:
+        dbg->hooks->gl.glUniform1fv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform1i:
+        dbg->hooks->gl.glUniform1i(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLint>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform1iv:
+        dbg->hooks->gl.glUniform1iv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            reinterpret_cast<GLint*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform2f:
+        dbg->hooks->gl.glUniform2f(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1()), 
+            static_cast<GLfloat>(cmd.arg2()));
+        break;
+    case glesv2debugger::Message_Function_glUniform2fv:
+        dbg->hooks->gl.glUniform2fv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform2i:
+        dbg->hooks->gl.glUniform2i(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLint>(cmd.arg2()));
+        break;
+    case glesv2debugger::Message_Function_glUniform2iv:
+        dbg->hooks->gl.glUniform2iv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            reinterpret_cast<GLint*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform3f:
+        dbg->hooks->gl.glUniform3f(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1()), 
+            static_cast<GLfloat>(cmd.arg2()), static_cast<GLfloat>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform3fv:
+        dbg->hooks->gl.glUniform3fv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform3i:
+        dbg->hooks->gl.glUniform3i(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLint>(cmd.arg2()), static_cast<GLint>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform3iv:
+        dbg->hooks->gl.glUniform3iv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            reinterpret_cast<GLint*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform4f:
+        dbg->hooks->gl.glUniform4f(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1()), 
+            static_cast<GLfloat>(cmd.arg2()), static_cast<GLfloat>(cmd.arg3()), 
+            static_cast<GLfloat>(cmd.arg4()));
+        break;
+    case glesv2debugger::Message_Function_glUniform4fv:
+        dbg->hooks->gl.glUniform4fv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniform4i:
+        dbg->hooks->gl.glUniform4i(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLint>(cmd.arg2()), static_cast<GLint>(cmd.arg3()), 
+            static_cast<GLint>(cmd.arg4()));
+        break;
+    case glesv2debugger::Message_Function_glUniform4iv:
+        dbg->hooks->gl.glUniform4iv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            reinterpret_cast<GLint*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniformMatrix2fv:
+        dbg->hooks->gl.glUniformMatrix2fv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            GLboolean(cmd.arg2()), reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniformMatrix3fv:
+        dbg->hooks->gl.glUniformMatrix3fv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            GLboolean(cmd.arg2()), reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUniformMatrix4fv:
+        dbg->hooks->gl.glUniformMatrix4fv(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLsizei>(cmd.arg1()), 
+            GLboolean(cmd.arg2()), reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glUseProgram:
+        dbg->hooks->gl.glUseProgram(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glValidateProgram:
+        dbg->hooks->gl.glValidateProgram(
+            static_cast<GLuint>(cmd.arg0()));
+        break;
+    case glesv2debugger::Message_Function_glVertexAttrib1f:
+        dbg->hooks->gl.glVertexAttrib1f(
+            static_cast<GLuint>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1())
+            );
+        break;
+    case glesv2debugger::Message_Function_glVertexAttrib1fv:
+        dbg->hooks->gl.glVertexAttrib1fv(
+            static_cast<GLuint>(cmd.arg0()), reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glVertexAttrib2f:
+        dbg->hooks->gl.glVertexAttrib2f(
+            static_cast<GLuint>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1()), 
+            static_cast<GLfloat>(cmd.arg2()));
+        break;
+    case glesv2debugger::Message_Function_glVertexAttrib2fv:
+        dbg->hooks->gl.glVertexAttrib2fv(
+            static_cast<GLuint>(cmd.arg0()), reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glVertexAttrib3f:
+        dbg->hooks->gl.glVertexAttrib3f(
+            static_cast<GLuint>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1()), 
+            static_cast<GLfloat>(cmd.arg2()), static_cast<GLfloat>(cmd.arg3())
+            );
+        break;
+    case glesv2debugger::Message_Function_glVertexAttrib3fv:
+        dbg->hooks->gl.glVertexAttrib3fv(
+            static_cast<GLuint>(cmd.arg0()), reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glVertexAttrib4f:
+        dbg->hooks->gl.glVertexAttrib4f(
+            static_cast<GLuint>(cmd.arg0()), static_cast<GLfloat>(cmd.arg1()), 
+            static_cast<GLfloat>(cmd.arg2()), static_cast<GLfloat>(cmd.arg3()), 
+            static_cast<GLfloat>(cmd.arg4()));
+        break;
+    case glesv2debugger::Message_Function_glVertexAttrib4fv:
+        dbg->hooks->gl.glVertexAttrib4fv(
+            static_cast<GLuint>(cmd.arg0()), reinterpret_cast<GLfloat*>(const_cast<char *>(cmd.data().data()))
+            );
+        break;
+    case glesv2debugger::Message_Function_glVertexAttribPointer:
+        ret = GenerateCall_glVertexAttribPointer(dbg, cmd, msg, prevRet);
+        break;
+    case glesv2debugger::Message_Function_glViewport:
+        dbg->hooks->gl.glViewport(
+            static_cast<GLint>(cmd.arg0()), static_cast<GLint>(cmd.arg1()), 
+            static_cast<GLsizei>(cmd.arg2()), static_cast<GLsizei>(cmd.arg3())
+            );
+        break;
+    default:
+        assert(0);
+    }
+    msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_function(cmd.function());
+    msg.set_type(glesv2debugger::Message_Type_AfterGeneratedCall);
+    return ret;
+}
+
+}; // name space android {
diff --git a/opengl/libs/GLES2_dbg/src/caller.h b/opengl/libs/GLES2_dbg/src/caller.h
new file mode 100644
index 0000000..e8111b3
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/caller.h
@@ -0,0 +1,330 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License")
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+static const int * GenerateCall_glCompressedTexImage2D(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glCompressedTexSubImage2D(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glDrawElements(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGenBuffers(DbgContext * const dbg,
+                                       const glesv2debugger::Message & cmd,
+                                       glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGenFramebuffers(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGenRenderbuffers(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGenTextures(DbgContext * const dbg,
+                                        const glesv2debugger::Message & cmd,
+                                        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetActiveAttrib(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetActiveUniform(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetAttachedShaders(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetBooleanv(DbgContext * const dbg,
+                                        const glesv2debugger::Message & cmd,
+                                        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetBufferParameteriv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetFloatv(DbgContext * const dbg,
+                                      const glesv2debugger::Message & cmd,
+                                      glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetFramebufferAttachmentParameteriv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetIntegerv(DbgContext * const dbg,
+                                        const glesv2debugger::Message & cmd,
+                                        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetProgramiv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    GLint params = -1;
+    dbg->hooks->gl.glGetProgramiv(cmd.arg0(), cmd.arg1(), &params);
+    msg.mutable_data()->append(reinterpret_cast<char *>(&params), sizeof(params));
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetProgramInfoLog(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    const GLsizei bufSize = static_cast<GLsizei>(dbg->GetBufferSize());
+    GLsizei length = -1;
+    dbg->hooks->gl.glGetProgramInfoLog(cmd.arg0(), bufSize, &length, dbg->GetBuffer());
+    msg.mutable_data()->append(dbg->GetBuffer(), length);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetRenderbufferParameteriv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetShaderiv(DbgContext * const dbg,
+                                        const glesv2debugger::Message & cmd,
+                                        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    GLint params = -1;
+    dbg->hooks->gl.glGetShaderiv(cmd.arg0(), cmd.arg1(), &params);
+    msg.mutable_data()->append(reinterpret_cast<char *>(&params), sizeof(params));
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetShaderInfoLog(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    const GLsizei bufSize = static_cast<GLsizei>(dbg->GetBufferSize());
+    GLsizei length = -1;
+    dbg->hooks->gl.glGetShaderInfoLog(cmd.arg0(), bufSize, &length, dbg->GetBuffer());
+    msg.mutable_data()->append(dbg->GetBuffer(), length);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetShaderPrecisionFormat(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetShaderSource(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetString(DbgContext * const dbg,
+                                      const glesv2debugger::Message & cmd,
+                                      glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetTexParameterfv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetTexParameteriv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetUniformfv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetUniformiv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetVertexAttribfv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetVertexAttribiv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glGetVertexAttribPointerv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glReadPixels(DbgContext * const dbg,
+                                       const glesv2debugger::Message & cmd,
+                                       glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glShaderBinary(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glShaderSource(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    const char * string = cmd.data().data();
+    dbg->hooks->gl.glShaderSource(cmd.arg0(), 1, &string, NULL);
+    return prevRet;
+}
+
+static const int * GenerateCall_glTexImage2D(DbgContext * const dbg,
+                                       const glesv2debugger::Message & cmd,
+                                       glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glTexParameterfv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glTexParameteriv(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glTexSubImage2D(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
+
+static const int * GenerateCall_glVertexAttribPointer(DbgContext * const dbg,
+        const glesv2debugger::Message & cmd,
+        glesv2debugger::Message & msg, const int * const prevRet)
+{
+    assert(0);
+    return prevRet;
+}
diff --git a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
new file mode 100644
index 0000000..ff9be3c
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
@@ -0,0 +1,435 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "header.h"
+
+extern "C" {
+#include "liblzf/lzf.h"
+}
+
+namespace android {
+
+static pthread_key_t dbgEGLThreadLocalStorageKey = -1;
+static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
+
+DbgContext * getDbgContextThreadSpecific() {
+    return (DbgContext*)pthread_getspecific(dbgEGLThreadLocalStorageKey);
+}
+
+DbgContext::DbgContext(const unsigned version, const gl_hooks_t * const hooks,
+                       const unsigned MAX_VERTEX_ATTRIBS, const GLenum readFormat,
+                       const GLenum readType)
+        : lzf_buf(NULL), lzf_readIndex(0), lzf_refSize(0), lzf_refBufSize(0)
+        , version(version), hooks(hooks)
+        , MAX_VERTEX_ATTRIBS(MAX_VERTEX_ATTRIBS)
+        , readFormat(readFormat), readType(readType)
+        , readBytesPerPixel(GetBytesPerPixel(readFormat, readType))
+        , captureSwap(0), captureDraw(0)
+        , vertexAttribs(new VertexAttrib[MAX_VERTEX_ATTRIBS])
+        , hasNonVBOAttribs(false), indexBuffers(NULL), indexBuffer(NULL)
+        , program(0), maxAttrib(0)
+{
+    lzf_ref[0] = lzf_ref[1] = NULL;
+    for (unsigned i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+        vertexAttribs[i] = VertexAttrib();
+    memset(&expectResponse, 0, sizeof(expectResponse));
+}
+
+DbgContext::~DbgContext()
+{
+    delete vertexAttribs;
+    free(lzf_buf);
+    free(lzf_ref[0]);
+    free(lzf_ref[1]);
+}
+
+DbgContext* CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks)
+{
+    pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
+    if (dbgEGLThreadLocalStorageKey == -1)
+        pthread_key_create(&dbgEGLThreadLocalStorageKey, NULL);
+    pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
+
+    assert(version < 2);
+    assert(GL_NO_ERROR == hooks->gl.glGetError());
+    GLint MAX_VERTEX_ATTRIBS = 0;
+    hooks->gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &MAX_VERTEX_ATTRIBS);
+    GLint readFormat, readType;
+    hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
+    hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
+    DbgContext* dbg = new DbgContext(version, hooks, MAX_VERTEX_ATTRIBS, readFormat, readType);
+
+    glesv2debugger::Message msg, cmd;
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_expect_response(false);
+    msg.set_type(msg.Response);
+    msg.set_function(msg.SETPROP);
+    msg.set_prop(msg.GLConstant);
+    msg.set_arg0(GL_MAX_VERTEX_ATTRIBS);
+    msg.set_arg1(MAX_VERTEX_ATTRIBS);
+    Send(msg, cmd);
+
+    GLint MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0;
+    hooks->gl.glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+    msg.set_arg0(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+    msg.set_arg1(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+    Send(msg, cmd);
+
+    *(DbgContext **)pthread_getspecific(dbgEGLThreadLocalStorageKey) = dbg;
+    return dbg;
+}
+
+void dbgReleaseThread() {
+    delete getDbgContextThreadSpecific();
+}
+
+unsigned GetBytesPerPixel(const GLenum format, const GLenum type)
+{
+    switch (type) {
+    case GL_UNSIGNED_SHORT_5_6_5:
+        return 2;
+    case GL_UNSIGNED_SHORT_4_4_4_4:
+        return 2;
+    case GL_UNSIGNED_SHORT_5_5_5_1:
+        return 2;
+    case GL_UNSIGNED_BYTE:
+        break;
+    default:
+        assert(0);
+    }
+
+    switch (format) {
+    case GL_ALPHA:
+        return 1;
+    case GL_LUMINANCE:
+        return 1;
+        break;
+    case GL_LUMINANCE_ALPHA:
+        return 2;
+    case GL_RGB:
+        return 3;
+    case GL_RGBA:
+        return 4;
+    default:
+        assert(0);
+        return 0;
+    }
+}
+
+void DbgContext::Fetch(const unsigned index, std::string * const data) const
+{
+    // VBO data is already on client, just send user pointer data
+    for (unsigned i = 0; i < maxAttrib; i++) {
+        if (!vertexAttribs[i].enabled)
+            continue;
+        if (vertexAttribs[i].buffer > 0)
+            continue;
+        const char * ptr = (const char *)vertexAttribs[i].ptr;
+        ptr += index * vertexAttribs[i].stride;
+        data->append(ptr, vertexAttribs[i].elemSize);
+    }
+}
+
+void DbgContext::Compress(const void * in_data, unsigned int in_len,
+                          std::string * const outStr)
+{
+    if (!lzf_buf)
+        lzf_buf = (char *)malloc(LZF_CHUNK_SIZE);
+    assert(lzf_buf);
+    const uint32_t totalDecompSize = in_len;
+    outStr->append((const char *)&totalDecompSize, sizeof(totalDecompSize));
+    for (unsigned int i = 0; i < in_len; i += LZF_CHUNK_SIZE) {
+        uint32_t chunkSize = LZF_CHUNK_SIZE;
+        if (i + LZF_CHUNK_SIZE > in_len)
+            chunkSize = in_len - i;
+        const uint32_t compSize = lzf_compress((const char *)in_data + i, chunkSize,
+                                               lzf_buf, LZF_CHUNK_SIZE);
+        outStr->append((const char *)&chunkSize, sizeof(chunkSize));
+        outStr->append((const char *)&compSize, sizeof(compSize));
+        if (compSize > 0)
+            outStr->append(lzf_buf, compSize);
+        else // compressed chunk bigger than LZF_CHUNK_SIZE (and uncompressed)
+            outStr->append((const char *)in_data + i, chunkSize);
+    }
+}
+
+unsigned char * DbgContext::Decompress(const void * in, const unsigned int inLen,
+                                       unsigned int * const outLen)
+{
+    assert(inLen > 4 * 3);
+    if (inLen < 4 * 3)
+        return NULL;
+    *outLen = *(uint32_t *)in;
+    unsigned char * const out = (unsigned char *)malloc(*outLen);
+    unsigned int outPos = 0;
+    const unsigned char * const end = (const unsigned char *)in + inLen;
+    for (const unsigned char * inData = (const unsigned char *)in + 4; inData < end; ) {
+        const uint32_t chunkOut = *(uint32_t *)inData;
+        inData += 4;
+        const uint32_t chunkIn = *(uint32_t *)inData;
+        inData += 4;
+        if (chunkIn > 0) {
+            assert(inData + chunkIn <= end);
+            assert(outPos + chunkOut <= *outLen);
+            outPos += lzf_decompress(inData, chunkIn, out + outPos, chunkOut);
+            inData += chunkIn;
+        } else {
+            assert(inData + chunkOut <= end);
+            assert(outPos + chunkOut <= *outLen);
+            memcpy(out + outPos, inData, chunkOut);
+            inData += chunkOut;
+            outPos += chunkOut;
+        }
+    }
+    return out;
+}
+
+void * DbgContext::GetReadPixelsBuffer(const unsigned size)
+{
+    if (lzf_refBufSize < size + 8) {
+        lzf_refBufSize = size + 8;
+        lzf_ref[0] = (unsigned *)realloc(lzf_ref[0], lzf_refBufSize);
+        assert(lzf_ref[0]);
+        memset(lzf_ref[0], 0, lzf_refBufSize);
+        lzf_ref[1] = (unsigned *)realloc(lzf_ref[1], lzf_refBufSize);
+        assert(lzf_ref[1]);
+        memset(lzf_ref[1], 0, lzf_refBufSize);
+    }
+    if (lzf_refSize != size) // need to clear unused ref to maintain consistency
+    { // since ref and src are swapped each time
+        memset((char *)lzf_ref[0] + lzf_refSize, 0, lzf_refBufSize - lzf_refSize);
+        memset((char *)lzf_ref[1] + lzf_refSize, 0, lzf_refBufSize - lzf_refSize);
+    }
+    lzf_refSize = size;
+    lzf_readIndex ^= 1;
+    return lzf_ref[lzf_readIndex];
+}
+
+void DbgContext::CompressReadPixelBuffer(std::string * const outStr)
+{
+    assert(lzf_ref[0] && lzf_ref[1]);
+    unsigned * const ref = lzf_ref[lzf_readIndex ^ 1];
+    unsigned * const src = lzf_ref[lzf_readIndex];
+    for (unsigned i = 0; i < lzf_refSize / sizeof(*ref) + 1; i++)
+        ref[i] ^= src[i];
+    Compress(ref, lzf_refSize, outStr);
+}
+
+char * DbgContext::GetBuffer()
+{
+    if (!lzf_buf)
+        lzf_buf = (char *)malloc(LZF_CHUNK_SIZE);
+    assert(lzf_buf);
+    return lzf_buf;
+}
+
+unsigned int DbgContext::GetBufferSize()
+{
+    if (!lzf_buf)
+        lzf_buf = (char *)malloc(LZF_CHUNK_SIZE);
+    assert(lzf_buf);
+    if (lzf_buf)
+        return LZF_CHUNK_SIZE;
+    else
+        return 0;
+}
+
+void DbgContext::glUseProgram(GLuint program)
+{
+    while (GLenum error = hooks->gl.glGetError())
+        LOGD("DbgContext::glUseProgram(%u): before glGetError() = 0x%.4X",
+             program, error);
+    this->program = program;
+    maxAttrib = 0;
+    if (program == 0)
+        return;
+    GLint activeAttributes = 0;
+    hooks->gl.glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttributes);
+    maxAttrib = 0;
+    GLint maxNameLen = -1;
+    hooks->gl.glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLen);
+    char * name = new char [maxNameLen + 1];
+    name[maxNameLen] = 0;
+    // find total number of attribute slots used
+    for (unsigned i = 0; i < activeAttributes; i++) {
+        GLint size = -1;
+        GLenum type = -1;
+        hooks->gl.glGetActiveAttrib(program, i, maxNameLen + 1, NULL, &size, &type, name);
+        GLint slot = hooks->gl.glGetAttribLocation(program, name);
+        assert(slot >= 0);
+        switch (type) {
+        case GL_FLOAT:
+        case GL_FLOAT_VEC2:
+        case GL_FLOAT_VEC3:
+        case GL_FLOAT_VEC4:
+            slot += size;
+            break;
+        case GL_FLOAT_MAT2:
+            slot += size * 2;
+            break;
+        case GL_FLOAT_MAT3:
+            slot += size * 3;
+            break;
+        case GL_FLOAT_MAT4:
+            slot += size * 4;
+            break;
+        default:
+            assert(0);
+        }
+        if (slot > maxAttrib)
+            maxAttrib = slot;
+    }
+    delete name;
+    while (GLenum error = hooks->gl.glGetError())
+        LOGD("DbgContext::glUseProgram(%u): after glGetError() = 0x%.4X",
+             program, error);
+}
+
+static bool HasNonVBOAttribs(const DbgContext * const ctx)
+{
+    bool need = false;
+    for (unsigned i = 0; !need && i < ctx->maxAttrib; i++)
+        if (ctx->vertexAttribs[i].enabled && ctx->vertexAttribs[i].buffer == 0)
+            need = true;
+    return need;
+}
+
+void DbgContext::glVertexAttribPointer(GLuint indx, GLint size, GLenum type,
+                                       GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+{
+    assert(GL_NO_ERROR == hooks->gl.glGetError());
+    assert(indx < MAX_VERTEX_ATTRIBS);
+    vertexAttribs[indx].size = size;
+    vertexAttribs[indx].type = type;
+    vertexAttribs[indx].normalized = normalized;
+    switch (type) {
+    case GL_FLOAT:
+        vertexAttribs[indx].elemSize = sizeof(GLfloat) * size;
+        break;
+    case GL_INT:
+    case GL_UNSIGNED_INT:
+        vertexAttribs[indx].elemSize = sizeof(GLint) * size;
+        break;
+    case GL_SHORT:
+    case GL_UNSIGNED_SHORT:
+        vertexAttribs[indx].elemSize = sizeof(GLshort) * size;
+        break;
+    case GL_BYTE:
+    case GL_UNSIGNED_BYTE:
+        vertexAttribs[indx].elemSize = sizeof(GLbyte) * size;
+        break;
+    default:
+        assert(0);
+    }
+    if (0 == stride)
+        stride = vertexAttribs[indx].elemSize;
+    vertexAttribs[indx].stride = stride;
+    vertexAttribs[indx].ptr = ptr;
+    hooks->gl.glGetVertexAttribiv(indx, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
+                                  (GLint *)&vertexAttribs[indx].buffer);
+    hasNonVBOAttribs = HasNonVBOAttribs(this);
+}
+
+void DbgContext::glEnableVertexAttribArray(GLuint index)
+{
+    if (index >= MAX_VERTEX_ATTRIBS)
+        return;
+    vertexAttribs[index].enabled = true;
+    hasNonVBOAttribs = HasNonVBOAttribs(this);
+}
+
+void DbgContext::glDisableVertexAttribArray(GLuint index)
+{
+    if (index >= MAX_VERTEX_ATTRIBS)
+        return;
+    vertexAttribs[index].enabled = false;
+    hasNonVBOAttribs = HasNonVBOAttribs(this);
+}
+
+void DbgContext::glBindBuffer(GLenum target, GLuint buffer)
+{
+    if (GL_ELEMENT_ARRAY_BUFFER != target)
+        return;
+    if (0 == buffer) {
+        indexBuffer = NULL;
+        return;
+    }
+    VBO * b = indexBuffers;
+    indexBuffer = NULL;
+    while (b) {
+        if (b->name == buffer) {
+            assert(GL_ELEMENT_ARRAY_BUFFER == b->target);
+            indexBuffer = b;
+            break;
+        }
+        b = b->next;
+    }
+    if (!indexBuffer)
+        indexBuffer = indexBuffers = new VBO(buffer, target, indexBuffers);
+}
+
+void DbgContext::glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+    if (GL_ELEMENT_ARRAY_BUFFER != target)
+        return;
+    assert(indexBuffer);
+    assert(size >= 0);
+    indexBuffer->size = size;
+    indexBuffer->data = realloc(indexBuffer->data, size);
+    memcpy(indexBuffer->data, data, size);
+}
+
+void DbgContext::glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+    if (GL_ELEMENT_ARRAY_BUFFER != target)
+        return;
+    assert(indexBuffer);
+    assert(size >= 0);
+    assert(offset >= 0);
+    assert(offset + size <= indexBuffer->size);
+    memcpy((char *)indexBuffer->data + offset, data, size);
+}
+
+void DbgContext::glDeleteBuffers(GLsizei n, const GLuint *buffers)
+{
+    for (unsigned i = 0; i < n; i++) {
+        for (unsigned j = 0; j < MAX_VERTEX_ATTRIBS; j++)
+            if (buffers[i] == vertexAttribs[j].buffer) {
+                vertexAttribs[j].buffer = 0;
+                vertexAttribs[j].enabled = false;
+            }
+        VBO * b = indexBuffers, * previous = NULL;
+        while (b) {
+            if (b->name == buffers[i]) {
+                assert(GL_ELEMENT_ARRAY_BUFFER == b->target);
+                if (indexBuffer == b)
+                    indexBuffer = NULL;
+                if (previous)
+                    previous->next = b->next;
+                else
+                    indexBuffers = b->next;
+                free(b->data);
+                delete b;
+                break;
+            }
+            previous = b;
+            b = b->next;
+        }
+    }
+    hasNonVBOAttribs = HasNonVBOAttribs(this);
+}
+
+}; // namespace android
diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
new file mode 100644
index 0000000..50f70f7
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
@@ -0,0 +1,1455 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "debugger_message.pb.h"
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+// @@protoc_insertion_point(includes)
+
+namespace com {
+namespace android {
+namespace glesv2debugger {
+
+void protobuf_ShutdownFile_debugger_5fmessage_2eproto() {
+  delete Message::default_instance_;
+}
+
+void protobuf_AddDesc_debugger_5fmessage_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  Message::default_instance_ = new Message();
+  Message::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_debugger_5fmessage_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_debugger_5fmessage_2eproto {
+  StaticDescriptorInitializer_debugger_5fmessage_2eproto() {
+    protobuf_AddDesc_debugger_5fmessage_2eproto();
+  }
+} static_descriptor_initializer_debugger_5fmessage_2eproto_;
+
+
+// ===================================================================
+
+bool Message_Function_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40:
+    case 41:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+    case 50:
+    case 51:
+    case 52:
+    case 53:
+    case 54:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
+    case 59:
+    case 60:
+    case 61:
+    case 62:
+    case 63:
+    case 64:
+    case 65:
+    case 66:
+    case 67:
+    case 68:
+    case 69:
+    case 70:
+    case 71:
+    case 72:
+    case 73:
+    case 74:
+    case 75:
+    case 76:
+    case 77:
+    case 78:
+    case 79:
+    case 80:
+    case 81:
+    case 82:
+    case 83:
+    case 84:
+    case 85:
+    case 86:
+    case 87:
+    case 88:
+    case 89:
+    case 90:
+    case 91:
+    case 92:
+    case 93:
+    case 94:
+    case 95:
+    case 96:
+    case 97:
+    case 98:
+    case 99:
+    case 100:
+    case 101:
+    case 102:
+    case 103:
+    case 104:
+    case 105:
+    case 106:
+    case 107:
+    case 108:
+    case 109:
+    case 110:
+    case 111:
+    case 112:
+    case 113:
+    case 114:
+    case 115:
+    case 116:
+    case 117:
+    case 118:
+    case 119:
+    case 120:
+    case 121:
+    case 122:
+    case 123:
+    case 124:
+    case 125:
+    case 126:
+    case 127:
+    case 128:
+    case 129:
+    case 130:
+    case 131:
+    case 132:
+    case 133:
+    case 134:
+    case 135:
+    case 136:
+    case 137:
+    case 138:
+    case 139:
+    case 140:
+    case 141:
+    case 142:
+    case 143:
+    case 144:
+    case 145:
+    case 146:
+    case 147:
+    case 148:
+    case 149:
+    case 150:
+    case 151:
+    case 152:
+    case 153:
+    case 154:
+    case 155:
+    case 156:
+    case 157:
+    case 158:
+    case 159:
+    case 160:
+    case 161:
+    case 162:
+    case 163:
+    case 164:
+    case 165:
+    case 166:
+    case 167:
+    case 168:
+    case 169:
+    case 170:
+    case 171:
+    case 172:
+    case 173:
+    case 174:
+    case 175:
+    case 176:
+    case 177:
+    case 178:
+    case 179:
+    case 180:
+    case 181:
+    case 182:
+    case 183:
+    case 184:
+    case 185:
+    case 186:
+    case 187:
+    case 188:
+    case 189:
+    case 190:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Function Message::glActiveTexture;
+const Message_Function Message::glAttachShader;
+const Message_Function Message::glBindAttribLocation;
+const Message_Function Message::glBindBuffer;
+const Message_Function Message::glBindFramebuffer;
+const Message_Function Message::glBindRenderbuffer;
+const Message_Function Message::glBindTexture;
+const Message_Function Message::glBlendColor;
+const Message_Function Message::glBlendEquation;
+const Message_Function Message::glBlendEquationSeparate;
+const Message_Function Message::glBlendFunc;
+const Message_Function Message::glBlendFuncSeparate;
+const Message_Function Message::glBufferData;
+const Message_Function Message::glBufferSubData;
+const Message_Function Message::glCheckFramebufferStatus;
+const Message_Function Message::glClear;
+const Message_Function Message::glClearColor;
+const Message_Function Message::glClearDepthf;
+const Message_Function Message::glClearStencil;
+const Message_Function Message::glColorMask;
+const Message_Function Message::glCompileShader;
+const Message_Function Message::glCompressedTexImage2D;
+const Message_Function Message::glCompressedTexSubImage2D;
+const Message_Function Message::glCopyTexImage2D;
+const Message_Function Message::glCopyTexSubImage2D;
+const Message_Function Message::glCreateProgram;
+const Message_Function Message::glCreateShader;
+const Message_Function Message::glCullFace;
+const Message_Function Message::glDeleteBuffers;
+const Message_Function Message::glDeleteFramebuffers;
+const Message_Function Message::glDeleteProgram;
+const Message_Function Message::glDeleteRenderbuffers;
+const Message_Function Message::glDeleteShader;
+const Message_Function Message::glDeleteTextures;
+const Message_Function Message::glDepthFunc;
+const Message_Function Message::glDepthMask;
+const Message_Function Message::glDepthRangef;
+const Message_Function Message::glDetachShader;
+const Message_Function Message::glDisable;
+const Message_Function Message::glDisableVertexAttribArray;
+const Message_Function Message::glDrawArrays;
+const Message_Function Message::glDrawElements;
+const Message_Function Message::glEnable;
+const Message_Function Message::glEnableVertexAttribArray;
+const Message_Function Message::glFinish;
+const Message_Function Message::glFlush;
+const Message_Function Message::glFramebufferRenderbuffer;
+const Message_Function Message::glFramebufferTexture2D;
+const Message_Function Message::glFrontFace;
+const Message_Function Message::glGenBuffers;
+const Message_Function Message::glGenerateMipmap;
+const Message_Function Message::glGenFramebuffers;
+const Message_Function Message::glGenRenderbuffers;
+const Message_Function Message::glGenTextures;
+const Message_Function Message::glGetActiveAttrib;
+const Message_Function Message::glGetActiveUniform;
+const Message_Function Message::glGetAttachedShaders;
+const Message_Function Message::glGetAttribLocation;
+const Message_Function Message::glGetBooleanv;
+const Message_Function Message::glGetBufferParameteriv;
+const Message_Function Message::glGetError;
+const Message_Function Message::glGetFloatv;
+const Message_Function Message::glGetFramebufferAttachmentParameteriv;
+const Message_Function Message::glGetIntegerv;
+const Message_Function Message::glGetProgramiv;
+const Message_Function Message::glGetProgramInfoLog;
+const Message_Function Message::glGetRenderbufferParameteriv;
+const Message_Function Message::glGetShaderiv;
+const Message_Function Message::glGetShaderInfoLog;
+const Message_Function Message::glGetShaderPrecisionFormat;
+const Message_Function Message::glGetShaderSource;
+const Message_Function Message::glGetString;
+const Message_Function Message::glGetTexParameterfv;
+const Message_Function Message::glGetTexParameteriv;
+const Message_Function Message::glGetUniformfv;
+const Message_Function Message::glGetUniformiv;
+const Message_Function Message::glGetUniformLocation;
+const Message_Function Message::glGetVertexAttribfv;
+const Message_Function Message::glGetVertexAttribiv;
+const Message_Function Message::glGetVertexAttribPointerv;
+const Message_Function Message::glHint;
+const Message_Function Message::glIsBuffer;
+const Message_Function Message::glIsEnabled;
+const Message_Function Message::glIsFramebuffer;
+const Message_Function Message::glIsProgram;
+const Message_Function Message::glIsRenderbuffer;
+const Message_Function Message::glIsShader;
+const Message_Function Message::glIsTexture;
+const Message_Function Message::glLineWidth;
+const Message_Function Message::glLinkProgram;
+const Message_Function Message::glPixelStorei;
+const Message_Function Message::glPolygonOffset;
+const Message_Function Message::glReadPixels;
+const Message_Function Message::glReleaseShaderCompiler;
+const Message_Function Message::glRenderbufferStorage;
+const Message_Function Message::glSampleCoverage;
+const Message_Function Message::glScissor;
+const Message_Function Message::glShaderBinary;
+const Message_Function Message::glShaderSource;
+const Message_Function Message::glStencilFunc;
+const Message_Function Message::glStencilFuncSeparate;
+const Message_Function Message::glStencilMask;
+const Message_Function Message::glStencilMaskSeparate;
+const Message_Function Message::glStencilOp;
+const Message_Function Message::glStencilOpSeparate;
+const Message_Function Message::glTexImage2D;
+const Message_Function Message::glTexParameterf;
+const Message_Function Message::glTexParameterfv;
+const Message_Function Message::glTexParameteri;
+const Message_Function Message::glTexParameteriv;
+const Message_Function Message::glTexSubImage2D;
+const Message_Function Message::glUniform1f;
+const Message_Function Message::glUniform1fv;
+const Message_Function Message::glUniform1i;
+const Message_Function Message::glUniform1iv;
+const Message_Function Message::glUniform2f;
+const Message_Function Message::glUniform2fv;
+const Message_Function Message::glUniform2i;
+const Message_Function Message::glUniform2iv;
+const Message_Function Message::glUniform3f;
+const Message_Function Message::glUniform3fv;
+const Message_Function Message::glUniform3i;
+const Message_Function Message::glUniform3iv;
+const Message_Function Message::glUniform4f;
+const Message_Function Message::glUniform4fv;
+const Message_Function Message::glUniform4i;
+const Message_Function Message::glUniform4iv;
+const Message_Function Message::glUniformMatrix2fv;
+const Message_Function Message::glUniformMatrix3fv;
+const Message_Function Message::glUniformMatrix4fv;
+const Message_Function Message::glUseProgram;
+const Message_Function Message::glValidateProgram;
+const Message_Function Message::glVertexAttrib1f;
+const Message_Function Message::glVertexAttrib1fv;
+const Message_Function Message::glVertexAttrib2f;
+const Message_Function Message::glVertexAttrib2fv;
+const Message_Function Message::glVertexAttrib3f;
+const Message_Function Message::glVertexAttrib3fv;
+const Message_Function Message::glVertexAttrib4f;
+const Message_Function Message::glVertexAttrib4fv;
+const Message_Function Message::glVertexAttribPointer;
+const Message_Function Message::glViewport;
+const Message_Function Message::eglGetDisplay;
+const Message_Function Message::eglInitialize;
+const Message_Function Message::eglTerminate;
+const Message_Function Message::eglGetConfigs;
+const Message_Function Message::eglChooseConfig;
+const Message_Function Message::eglGetConfigAttrib;
+const Message_Function Message::eglCreateWindowSurface;
+const Message_Function Message::eglCreatePixmapSurface;
+const Message_Function Message::eglCreatePbufferSurface;
+const Message_Function Message::eglDestroySurface;
+const Message_Function Message::eglQuerySurface;
+const Message_Function Message::eglCreateContext;
+const Message_Function Message::eglDestroyContext;
+const Message_Function Message::eglMakeCurrent;
+const Message_Function Message::eglGetCurrentContext;
+const Message_Function Message::eglGetCurrentSurface;
+const Message_Function Message::eglGetCurrentDisplay;
+const Message_Function Message::eglQueryContext;
+const Message_Function Message::eglWaitGL;
+const Message_Function Message::eglWaitNative;
+const Message_Function Message::eglSwapBuffers;
+const Message_Function Message::eglCopyBuffers;
+const Message_Function Message::eglGetError;
+const Message_Function Message::eglQueryString;
+const Message_Function Message::eglGetProcAddress;
+const Message_Function Message::eglSurfaceAttrib;
+const Message_Function Message::eglBindTexImage;
+const Message_Function Message::eglReleaseTexImage;
+const Message_Function Message::eglSwapInterval;
+const Message_Function Message::eglBindAPI;
+const Message_Function Message::eglQueryAPI;
+const Message_Function Message::eglWaitClient;
+const Message_Function Message::eglReleaseThread;
+const Message_Function Message::eglCreatePbufferFromClientBuffer;
+const Message_Function Message::eglLockSurfaceKHR;
+const Message_Function Message::eglUnlockSurfaceKHR;
+const Message_Function Message::eglCreateImageKHR;
+const Message_Function Message::eglDestroyImageKHR;
+const Message_Function Message::eglCreateSyncKHR;
+const Message_Function Message::eglDestroySyncKHR;
+const Message_Function Message::eglClientWaitSyncKHR;
+const Message_Function Message::eglGetSyncAttribKHR;
+const Message_Function Message::eglSetSwapRectangleANDROID;
+const Message_Function Message::eglGetRenderBufferANDROID;
+const Message_Function Message::ACK;
+const Message_Function Message::NEG;
+const Message_Function Message::CONTINUE;
+const Message_Function Message::SKIP;
+const Message_Function Message::SETPROP;
+const Message_Function Message::Function_MIN;
+const Message_Function Message::Function_MAX;
+const int Message::Function_ARRAYSIZE;
+#endif  // _MSC_VER
+bool Message_Type_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Type Message::BeforeCall;
+const Message_Type Message::AfterCall;
+const Message_Type Message::AfterGeneratedCall;
+const Message_Type Message::Response;
+const Message_Type Message::CompleteCall;
+const Message_Type Message::Type_MIN;
+const Message_Type Message::Type_MAX;
+const int Message::Type_ARRAYSIZE;
+#endif  // _MSC_VER
+bool Message_DataType_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_DataType Message::ReferencedImage;
+const Message_DataType Message::NonreferencedImage;
+const Message_DataType Message::DataType_MIN;
+const Message_DataType Message::DataType_MAX;
+const int Message::DataType_ARRAYSIZE;
+#endif  // _MSC_VER
+bool Message_Prop_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Prop Message::CaptureDraw;
+const Message_Prop Message::TimeMode;
+const Message_Prop Message::ExpectResponse;
+const Message_Prop Message::CaptureSwap;
+const Message_Prop Message::GLConstant;
+const Message_Prop Message::Prop_MIN;
+const Message_Prop Message::Prop_MAX;
+const int Message::Prop_ARRAYSIZE;
+#endif  // _MSC_VER
+const ::std::string Message::_default_data_;
+#ifndef _MSC_VER
+const int Message::kContextIdFieldNumber;
+const int Message::kFunctionFieldNumber;
+const int Message::kTypeFieldNumber;
+const int Message::kExpectResponseFieldNumber;
+const int Message::kRetFieldNumber;
+const int Message::kArg0FieldNumber;
+const int Message::kArg1FieldNumber;
+const int Message::kArg2FieldNumber;
+const int Message::kArg3FieldNumber;
+const int Message::kArg4FieldNumber;
+const int Message::kArg5FieldNumber;
+const int Message::kArg6FieldNumber;
+const int Message::kArg7FieldNumber;
+const int Message::kArg8FieldNumber;
+const int Message::kDataFieldNumber;
+const int Message::kDataTypeFieldNumber;
+const int Message::kPixelFormatFieldNumber;
+const int Message::kPixelTypeFieldNumber;
+const int Message::kImageWidthFieldNumber;
+const int Message::kImageHeightFieldNumber;
+const int Message::kTimeFieldNumber;
+const int Message::kPropFieldNumber;
+const int Message::kClockFieldNumber;
+#endif  // !_MSC_VER
+
+Message::Message()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+}
+
+void Message::InitAsDefaultInstance() {
+}
+
+Message::Message(const Message& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void Message::SharedCtor() {
+  _cached_size_ = 0;
+  context_id_ = 0;
+  function_ = 187;
+  type_ = 0;
+  expect_response_ = false;
+  ret_ = 0;
+  arg0_ = 0;
+  arg1_ = 0;
+  arg2_ = 0;
+  arg3_ = 0;
+  arg4_ = 0;
+  arg5_ = 0;
+  arg6_ = 0;
+  arg7_ = 0;
+  arg8_ = 0;
+  data_ = const_cast< ::std::string*>(&_default_data_);
+  data_type_ = 0;
+  pixel_format_ = 0;
+  pixel_type_ = 0;
+  image_width_ = 0;
+  image_height_ = 0;
+  time_ = 0;
+  prop_ = 0;
+  clock_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+Message::~Message() {
+  SharedDtor();
+}
+
+void Message::SharedDtor() {
+  if (data_ != &_default_data_) {
+    delete data_;
+  }
+  if (this != default_instance_) {
+  }
+}
+
+void Message::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const Message& Message::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_debugger_5fmessage_2eproto();  return *default_instance_;
+}
+
+Message* Message::default_instance_ = NULL;
+
+Message* Message::New() const {
+  return new Message;
+}
+
+void Message::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    context_id_ = 0;
+    function_ = 187;
+    type_ = 0;
+    expect_response_ = false;
+    ret_ = 0;
+    arg0_ = 0;
+    arg1_ = 0;
+    arg2_ = 0;
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    arg3_ = 0;
+    arg4_ = 0;
+    arg5_ = 0;
+    arg6_ = 0;
+    arg7_ = 0;
+    arg8_ = 0;
+    if (_has_bit(14)) {
+      if (data_ != &_default_data_) {
+        data_->clear();
+      }
+    }
+    data_type_ = 0;
+  }
+  if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    pixel_format_ = 0;
+    pixel_type_ = 0;
+    image_width_ = 0;
+    image_height_ = 0;
+    time_ = 0;
+    prop_ = 0;
+    clock_ = 0;
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+bool Message::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required int32 context_id = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &context_id_)));
+          _set_bit(0);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(16)) goto parse_function;
+        break;
+      }
+      
+      // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_function:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Function_IsValid(value)) {
+            set_function(static_cast< ::com::android::glesv2debugger::Message_Function >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(24)) goto parse_type;
+        break;
+      }
+      
+      // required .com.android.glesv2debugger.Message.Type type = 3;
+      case 3: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_type:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Type_IsValid(value)) {
+            set_type(static_cast< ::com::android::glesv2debugger::Message_Type >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(32)) goto parse_expect_response;
+        break;
+      }
+      
+      // required bool expect_response = 4;
+      case 4: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_expect_response:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &expect_response_)));
+          _set_bit(3);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(40)) goto parse_ret;
+        break;
+      }
+      
+      // optional int32 ret = 5;
+      case 5: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_ret:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &ret_)));
+          _set_bit(4);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(48)) goto parse_arg0;
+        break;
+      }
+      
+      // optional int32 arg0 = 6;
+      case 6: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg0:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg0_)));
+          _set_bit(5);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(56)) goto parse_arg1;
+        break;
+      }
+      
+      // optional int32 arg1 = 7;
+      case 7: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg1:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg1_)));
+          _set_bit(6);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(64)) goto parse_arg2;
+        break;
+      }
+      
+      // optional int32 arg2 = 8;
+      case 8: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg2:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg2_)));
+          _set_bit(7);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(72)) goto parse_arg3;
+        break;
+      }
+      
+      // optional int32 arg3 = 9;
+      case 9: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg3:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg3_)));
+          _set_bit(8);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(82)) goto parse_data;
+        break;
+      }
+      
+      // optional bytes data = 10;
+      case 10: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_data:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_data()));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(93)) goto parse_time;
+        break;
+      }
+      
+      // optional float time = 11;
+      case 11: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_time:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &time_)));
+          _set_bit(20);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(128)) goto parse_arg4;
+        break;
+      }
+      
+      // optional int32 arg4 = 16;
+      case 16: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg4:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg4_)));
+          _set_bit(9);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(136)) goto parse_arg5;
+        break;
+      }
+      
+      // optional int32 arg5 = 17;
+      case 17: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg5:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg5_)));
+          _set_bit(10);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(144)) goto parse_arg6;
+        break;
+      }
+      
+      // optional int32 arg6 = 18;
+      case 18: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg6:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg6_)));
+          _set_bit(11);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(152)) goto parse_arg7;
+        break;
+      }
+      
+      // optional int32 arg7 = 19;
+      case 19: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg7:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg7_)));
+          _set_bit(12);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(160)) goto parse_arg8;
+        break;
+      }
+      
+      // optional int32 arg8 = 20;
+      case 20: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg8:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg8_)));
+          _set_bit(13);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(168)) goto parse_prop;
+        break;
+      }
+      
+      // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+      case 21: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_prop:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Prop_IsValid(value)) {
+            set_prop(static_cast< ::com::android::glesv2debugger::Message_Prop >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(181)) goto parse_clock;
+        break;
+      }
+      
+      // optional float clock = 22;
+      case 22: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_clock:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &clock_)));
+          _set_bit(22);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(184)) goto parse_data_type;
+        break;
+      }
+      
+      // optional .com.android.glesv2debugger.Message.DataType data_type = 23;
+      case 23: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_data_type:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_DataType_IsValid(value)) {
+            set_data_type(static_cast< ::com::android::glesv2debugger::Message_DataType >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(192)) goto parse_pixel_format;
+        break;
+      }
+      
+      // optional int32 pixel_format = 24;
+      case 24: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_pixel_format:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &pixel_format_)));
+          _set_bit(16);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(200)) goto parse_pixel_type;
+        break;
+      }
+      
+      // optional int32 pixel_type = 25;
+      case 25: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_pixel_type:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &pixel_type_)));
+          _set_bit(17);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(208)) goto parse_image_width;
+        break;
+      }
+      
+      // optional int32 image_width = 26;
+      case 26: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_image_width:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &image_width_)));
+          _set_bit(18);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(216)) goto parse_image_height;
+        break;
+      }
+      
+      // optional int32 image_height = 27;
+      case 27: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_image_height:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &image_height_)));
+          _set_bit(19);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void Message::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // required int32 context_id = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->context_id(), output);
+  }
+  
+  // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->function(), output);
+  }
+  
+  // required .com.android.glesv2debugger.Message.Type type = 3;
+  if (_has_bit(2)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->type(), output);
+  }
+  
+  // required bool expect_response = 4;
+  if (_has_bit(3)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(4, this->expect_response(), output);
+  }
+  
+  // optional int32 ret = 5;
+  if (_has_bit(4)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(5, this->ret(), output);
+  }
+  
+  // optional int32 arg0 = 6;
+  if (_has_bit(5)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(6, this->arg0(), output);
+  }
+  
+  // optional int32 arg1 = 7;
+  if (_has_bit(6)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(7, this->arg1(), output);
+  }
+  
+  // optional int32 arg2 = 8;
+  if (_has_bit(7)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(8, this->arg2(), output);
+  }
+  
+  // optional int32 arg3 = 9;
+  if (_has_bit(8)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->arg3(), output);
+  }
+  
+  // optional bytes data = 10;
+  if (_has_bit(14)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytes(
+      10, this->data(), output);
+  }
+  
+  // optional float time = 11;
+  if (_has_bit(20)) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(11, this->time(), output);
+  }
+  
+  // optional int32 arg4 = 16;
+  if (_has_bit(9)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(16, this->arg4(), output);
+  }
+  
+  // optional int32 arg5 = 17;
+  if (_has_bit(10)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(17, this->arg5(), output);
+  }
+  
+  // optional int32 arg6 = 18;
+  if (_has_bit(11)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(18, this->arg6(), output);
+  }
+  
+  // optional int32 arg7 = 19;
+  if (_has_bit(12)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(19, this->arg7(), output);
+  }
+  
+  // optional int32 arg8 = 20;
+  if (_has_bit(13)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(20, this->arg8(), output);
+  }
+  
+  // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+  if (_has_bit(21)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      21, this->prop(), output);
+  }
+  
+  // optional float clock = 22;
+  if (_has_bit(22)) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(22, this->clock(), output);
+  }
+  
+  // optional .com.android.glesv2debugger.Message.DataType data_type = 23;
+  if (_has_bit(15)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      23, this->data_type(), output);
+  }
+  
+  // optional int32 pixel_format = 24;
+  if (_has_bit(16)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(24, this->pixel_format(), output);
+  }
+  
+  // optional int32 pixel_type = 25;
+  if (_has_bit(17)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(25, this->pixel_type(), output);
+  }
+  
+  // optional int32 image_width = 26;
+  if (_has_bit(18)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(26, this->image_width(), output);
+  }
+  
+  // optional int32 image_height = 27;
+  if (_has_bit(19)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(27, this->image_height(), output);
+  }
+  
+}
+
+int Message::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required int32 context_id = 1;
+    if (has_context_id()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->context_id());
+    }
+    
+    // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+    if (has_function()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->function());
+    }
+    
+    // required .com.android.glesv2debugger.Message.Type type = 3;
+    if (has_type()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
+    }
+    
+    // required bool expect_response = 4;
+    if (has_expect_response()) {
+      total_size += 1 + 1;
+    }
+    
+    // optional int32 ret = 5;
+    if (has_ret()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->ret());
+    }
+    
+    // optional int32 arg0 = 6;
+    if (has_arg0()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg0());
+    }
+    
+    // optional int32 arg1 = 7;
+    if (has_arg1()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg1());
+    }
+    
+    // optional int32 arg2 = 8;
+    if (has_arg2()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg2());
+    }
+    
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    // optional int32 arg3 = 9;
+    if (has_arg3()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg3());
+    }
+    
+    // optional int32 arg4 = 16;
+    if (has_arg4()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg4());
+    }
+    
+    // optional int32 arg5 = 17;
+    if (has_arg5()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg5());
+    }
+    
+    // optional int32 arg6 = 18;
+    if (has_arg6()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg6());
+    }
+    
+    // optional int32 arg7 = 19;
+    if (has_arg7()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg7());
+    }
+    
+    // optional int32 arg8 = 20;
+    if (has_arg8()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg8());
+    }
+    
+    // optional bytes data = 10;
+    if (has_data()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->data());
+    }
+    
+    // optional .com.android.glesv2debugger.Message.DataType data_type = 23;
+    if (has_data_type()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->data_type());
+    }
+    
+  }
+  if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    // optional int32 pixel_format = 24;
+    if (has_pixel_format()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->pixel_format());
+    }
+    
+    // optional int32 pixel_type = 25;
+    if (has_pixel_type()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->pixel_type());
+    }
+    
+    // optional int32 image_width = 26;
+    if (has_image_width()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->image_width());
+    }
+    
+    // optional int32 image_height = 27;
+    if (has_image_height()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->image_height());
+    }
+    
+    // optional float time = 11;
+    if (has_time()) {
+      total_size += 1 + 4;
+    }
+    
+    // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+    if (has_prop()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->prop());
+    }
+    
+    // optional float clock = 22;
+    if (has_clock()) {
+      total_size += 2 + 4;
+    }
+    
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Message::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const Message*>(&from));
+}
+
+void Message::MergeFrom(const Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from._has_bit(0)) {
+      set_context_id(from.context_id());
+    }
+    if (from._has_bit(1)) {
+      set_function(from.function());
+    }
+    if (from._has_bit(2)) {
+      set_type(from.type());
+    }
+    if (from._has_bit(3)) {
+      set_expect_response(from.expect_response());
+    }
+    if (from._has_bit(4)) {
+      set_ret(from.ret());
+    }
+    if (from._has_bit(5)) {
+      set_arg0(from.arg0());
+    }
+    if (from._has_bit(6)) {
+      set_arg1(from.arg1());
+    }
+    if (from._has_bit(7)) {
+      set_arg2(from.arg2());
+    }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from._has_bit(8)) {
+      set_arg3(from.arg3());
+    }
+    if (from._has_bit(9)) {
+      set_arg4(from.arg4());
+    }
+    if (from._has_bit(10)) {
+      set_arg5(from.arg5());
+    }
+    if (from._has_bit(11)) {
+      set_arg6(from.arg6());
+    }
+    if (from._has_bit(12)) {
+      set_arg7(from.arg7());
+    }
+    if (from._has_bit(13)) {
+      set_arg8(from.arg8());
+    }
+    if (from._has_bit(14)) {
+      set_data(from.data());
+    }
+    if (from._has_bit(15)) {
+      set_data_type(from.data_type());
+    }
+  }
+  if (from._has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    if (from._has_bit(16)) {
+      set_pixel_format(from.pixel_format());
+    }
+    if (from._has_bit(17)) {
+      set_pixel_type(from.pixel_type());
+    }
+    if (from._has_bit(18)) {
+      set_image_width(from.image_width());
+    }
+    if (from._has_bit(19)) {
+      set_image_height(from.image_height());
+    }
+    if (from._has_bit(20)) {
+      set_time(from.time());
+    }
+    if (from._has_bit(21)) {
+      set_prop(from.prop());
+    }
+    if (from._has_bit(22)) {
+      set_clock(from.clock());
+    }
+  }
+}
+
+void Message::CopyFrom(const Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Message::IsInitialized() const {
+  if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false;
+  
+  return true;
+}
+
+void Message::Swap(Message* other) {
+  if (other != this) {
+    std::swap(context_id_, other->context_id_);
+    std::swap(function_, other->function_);
+    std::swap(type_, other->type_);
+    std::swap(expect_response_, other->expect_response_);
+    std::swap(ret_, other->ret_);
+    std::swap(arg0_, other->arg0_);
+    std::swap(arg1_, other->arg1_);
+    std::swap(arg2_, other->arg2_);
+    std::swap(arg3_, other->arg3_);
+    std::swap(arg4_, other->arg4_);
+    std::swap(arg5_, other->arg5_);
+    std::swap(arg6_, other->arg6_);
+    std::swap(arg7_, other->arg7_);
+    std::swap(arg8_, other->arg8_);
+    std::swap(data_, other->data_);
+    std::swap(data_type_, other->data_type_);
+    std::swap(pixel_format_, other->pixel_format_);
+    std::swap(pixel_type_, other->pixel_type_);
+    std::swap(image_width_, other->image_width_);
+    std::swap(image_height_, other->image_height_);
+    std::swap(time_, other->time_);
+    std::swap(prop_, other->prop_);
+    std::swap(clock_, other->clock_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string Message::GetTypeName() const {
+  return "com.android.glesv2debugger.Message";
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace glesv2debugger
+}  // namespace android
+}  // namespace com
+
+// @@protoc_insertion_point(global_scope)
diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
new file mode 100644
index 0000000..5c94664
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
@@ -0,0 +1,1187 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: debugger_message.proto
+
+#ifndef PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
+#define PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 2003000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace com {
+namespace android {
+namespace glesv2debugger {
+
+// Internal implementation detail -- do not call these.
+void  protobuf_AddDesc_debugger_5fmessage_2eproto();
+void protobuf_AssignDesc_debugger_5fmessage_2eproto();
+void protobuf_ShutdownFile_debugger_5fmessage_2eproto();
+
+class Message;
+
+enum Message_Function {
+  Message_Function_glActiveTexture = 0,
+  Message_Function_glAttachShader = 1,
+  Message_Function_glBindAttribLocation = 2,
+  Message_Function_glBindBuffer = 3,
+  Message_Function_glBindFramebuffer = 4,
+  Message_Function_glBindRenderbuffer = 5,
+  Message_Function_glBindTexture = 6,
+  Message_Function_glBlendColor = 7,
+  Message_Function_glBlendEquation = 8,
+  Message_Function_glBlendEquationSeparate = 9,
+  Message_Function_glBlendFunc = 10,
+  Message_Function_glBlendFuncSeparate = 11,
+  Message_Function_glBufferData = 12,
+  Message_Function_glBufferSubData = 13,
+  Message_Function_glCheckFramebufferStatus = 14,
+  Message_Function_glClear = 15,
+  Message_Function_glClearColor = 16,
+  Message_Function_glClearDepthf = 17,
+  Message_Function_glClearStencil = 18,
+  Message_Function_glColorMask = 19,
+  Message_Function_glCompileShader = 20,
+  Message_Function_glCompressedTexImage2D = 21,
+  Message_Function_glCompressedTexSubImage2D = 22,
+  Message_Function_glCopyTexImage2D = 23,
+  Message_Function_glCopyTexSubImage2D = 24,
+  Message_Function_glCreateProgram = 25,
+  Message_Function_glCreateShader = 26,
+  Message_Function_glCullFace = 27,
+  Message_Function_glDeleteBuffers = 28,
+  Message_Function_glDeleteFramebuffers = 29,
+  Message_Function_glDeleteProgram = 30,
+  Message_Function_glDeleteRenderbuffers = 31,
+  Message_Function_glDeleteShader = 32,
+  Message_Function_glDeleteTextures = 33,
+  Message_Function_glDepthFunc = 34,
+  Message_Function_glDepthMask = 35,
+  Message_Function_glDepthRangef = 36,
+  Message_Function_glDetachShader = 37,
+  Message_Function_glDisable = 38,
+  Message_Function_glDisableVertexAttribArray = 39,
+  Message_Function_glDrawArrays = 40,
+  Message_Function_glDrawElements = 41,
+  Message_Function_glEnable = 42,
+  Message_Function_glEnableVertexAttribArray = 43,
+  Message_Function_glFinish = 44,
+  Message_Function_glFlush = 45,
+  Message_Function_glFramebufferRenderbuffer = 46,
+  Message_Function_glFramebufferTexture2D = 47,
+  Message_Function_glFrontFace = 48,
+  Message_Function_glGenBuffers = 49,
+  Message_Function_glGenerateMipmap = 50,
+  Message_Function_glGenFramebuffers = 51,
+  Message_Function_glGenRenderbuffers = 52,
+  Message_Function_glGenTextures = 53,
+  Message_Function_glGetActiveAttrib = 54,
+  Message_Function_glGetActiveUniform = 55,
+  Message_Function_glGetAttachedShaders = 56,
+  Message_Function_glGetAttribLocation = 57,
+  Message_Function_glGetBooleanv = 58,
+  Message_Function_glGetBufferParameteriv = 59,
+  Message_Function_glGetError = 60,
+  Message_Function_glGetFloatv = 61,
+  Message_Function_glGetFramebufferAttachmentParameteriv = 62,
+  Message_Function_glGetIntegerv = 63,
+  Message_Function_glGetProgramiv = 64,
+  Message_Function_glGetProgramInfoLog = 65,
+  Message_Function_glGetRenderbufferParameteriv = 66,
+  Message_Function_glGetShaderiv = 67,
+  Message_Function_glGetShaderInfoLog = 68,
+  Message_Function_glGetShaderPrecisionFormat = 69,
+  Message_Function_glGetShaderSource = 70,
+  Message_Function_glGetString = 71,
+  Message_Function_glGetTexParameterfv = 72,
+  Message_Function_glGetTexParameteriv = 73,
+  Message_Function_glGetUniformfv = 74,
+  Message_Function_glGetUniformiv = 75,
+  Message_Function_glGetUniformLocation = 76,
+  Message_Function_glGetVertexAttribfv = 77,
+  Message_Function_glGetVertexAttribiv = 78,
+  Message_Function_glGetVertexAttribPointerv = 79,
+  Message_Function_glHint = 80,
+  Message_Function_glIsBuffer = 81,
+  Message_Function_glIsEnabled = 82,
+  Message_Function_glIsFramebuffer = 83,
+  Message_Function_glIsProgram = 84,
+  Message_Function_glIsRenderbuffer = 85,
+  Message_Function_glIsShader = 86,
+  Message_Function_glIsTexture = 87,
+  Message_Function_glLineWidth = 88,
+  Message_Function_glLinkProgram = 89,
+  Message_Function_glPixelStorei = 90,
+  Message_Function_glPolygonOffset = 91,
+  Message_Function_glReadPixels = 92,
+  Message_Function_glReleaseShaderCompiler = 93,
+  Message_Function_glRenderbufferStorage = 94,
+  Message_Function_glSampleCoverage = 95,
+  Message_Function_glScissor = 96,
+  Message_Function_glShaderBinary = 97,
+  Message_Function_glShaderSource = 98,
+  Message_Function_glStencilFunc = 99,
+  Message_Function_glStencilFuncSeparate = 100,
+  Message_Function_glStencilMask = 101,
+  Message_Function_glStencilMaskSeparate = 102,
+  Message_Function_glStencilOp = 103,
+  Message_Function_glStencilOpSeparate = 104,
+  Message_Function_glTexImage2D = 105,
+  Message_Function_glTexParameterf = 106,
+  Message_Function_glTexParameterfv = 107,
+  Message_Function_glTexParameteri = 108,
+  Message_Function_glTexParameteriv = 109,
+  Message_Function_glTexSubImage2D = 110,
+  Message_Function_glUniform1f = 111,
+  Message_Function_glUniform1fv = 112,
+  Message_Function_glUniform1i = 113,
+  Message_Function_glUniform1iv = 114,
+  Message_Function_glUniform2f = 115,
+  Message_Function_glUniform2fv = 116,
+  Message_Function_glUniform2i = 117,
+  Message_Function_glUniform2iv = 118,
+  Message_Function_glUniform3f = 119,
+  Message_Function_glUniform3fv = 120,
+  Message_Function_glUniform3i = 121,
+  Message_Function_glUniform3iv = 122,
+  Message_Function_glUniform4f = 123,
+  Message_Function_glUniform4fv = 124,
+  Message_Function_glUniform4i = 125,
+  Message_Function_glUniform4iv = 126,
+  Message_Function_glUniformMatrix2fv = 127,
+  Message_Function_glUniformMatrix3fv = 128,
+  Message_Function_glUniformMatrix4fv = 129,
+  Message_Function_glUseProgram = 130,
+  Message_Function_glValidateProgram = 131,
+  Message_Function_glVertexAttrib1f = 132,
+  Message_Function_glVertexAttrib1fv = 133,
+  Message_Function_glVertexAttrib2f = 134,
+  Message_Function_glVertexAttrib2fv = 135,
+  Message_Function_glVertexAttrib3f = 136,
+  Message_Function_glVertexAttrib3fv = 137,
+  Message_Function_glVertexAttrib4f = 138,
+  Message_Function_glVertexAttrib4fv = 139,
+  Message_Function_glVertexAttribPointer = 140,
+  Message_Function_glViewport = 141,
+  Message_Function_eglGetDisplay = 142,
+  Message_Function_eglInitialize = 143,
+  Message_Function_eglTerminate = 144,
+  Message_Function_eglGetConfigs = 145,
+  Message_Function_eglChooseConfig = 146,
+  Message_Function_eglGetConfigAttrib = 147,
+  Message_Function_eglCreateWindowSurface = 148,
+  Message_Function_eglCreatePixmapSurface = 149,
+  Message_Function_eglCreatePbufferSurface = 150,
+  Message_Function_eglDestroySurface = 151,
+  Message_Function_eglQuerySurface = 152,
+  Message_Function_eglCreateContext = 153,
+  Message_Function_eglDestroyContext = 154,
+  Message_Function_eglMakeCurrent = 155,
+  Message_Function_eglGetCurrentContext = 156,
+  Message_Function_eglGetCurrentSurface = 157,
+  Message_Function_eglGetCurrentDisplay = 158,
+  Message_Function_eglQueryContext = 159,
+  Message_Function_eglWaitGL = 160,
+  Message_Function_eglWaitNative = 161,
+  Message_Function_eglSwapBuffers = 162,
+  Message_Function_eglCopyBuffers = 163,
+  Message_Function_eglGetError = 164,
+  Message_Function_eglQueryString = 165,
+  Message_Function_eglGetProcAddress = 166,
+  Message_Function_eglSurfaceAttrib = 167,
+  Message_Function_eglBindTexImage = 168,
+  Message_Function_eglReleaseTexImage = 169,
+  Message_Function_eglSwapInterval = 170,
+  Message_Function_eglBindAPI = 171,
+  Message_Function_eglQueryAPI = 172,
+  Message_Function_eglWaitClient = 173,
+  Message_Function_eglReleaseThread = 174,
+  Message_Function_eglCreatePbufferFromClientBuffer = 175,
+  Message_Function_eglLockSurfaceKHR = 176,
+  Message_Function_eglUnlockSurfaceKHR = 177,
+  Message_Function_eglCreateImageKHR = 178,
+  Message_Function_eglDestroyImageKHR = 179,
+  Message_Function_eglCreateSyncKHR = 180,
+  Message_Function_eglDestroySyncKHR = 181,
+  Message_Function_eglClientWaitSyncKHR = 182,
+  Message_Function_eglGetSyncAttribKHR = 183,
+  Message_Function_eglSetSwapRectangleANDROID = 184,
+  Message_Function_eglGetRenderBufferANDROID = 185,
+  Message_Function_ACK = 186,
+  Message_Function_NEG = 187,
+  Message_Function_CONTINUE = 188,
+  Message_Function_SKIP = 189,
+  Message_Function_SETPROP = 190
+};
+bool Message_Function_IsValid(int value);
+const Message_Function Message_Function_Function_MIN = Message_Function_glActiveTexture;
+const Message_Function Message_Function_Function_MAX = Message_Function_SETPROP;
+const int Message_Function_Function_ARRAYSIZE = Message_Function_Function_MAX + 1;
+
+enum Message_Type {
+  Message_Type_BeforeCall = 0,
+  Message_Type_AfterCall = 1,
+  Message_Type_AfterGeneratedCall = 2,
+  Message_Type_Response = 3,
+  Message_Type_CompleteCall = 4
+};
+bool Message_Type_IsValid(int value);
+const Message_Type Message_Type_Type_MIN = Message_Type_BeforeCall;
+const Message_Type Message_Type_Type_MAX = Message_Type_CompleteCall;
+const int Message_Type_Type_ARRAYSIZE = Message_Type_Type_MAX + 1;
+
+enum Message_DataType {
+  Message_DataType_ReferencedImage = 0,
+  Message_DataType_NonreferencedImage = 1
+};
+bool Message_DataType_IsValid(int value);
+const Message_DataType Message_DataType_DataType_MIN = Message_DataType_ReferencedImage;
+const Message_DataType Message_DataType_DataType_MAX = Message_DataType_NonreferencedImage;
+const int Message_DataType_DataType_ARRAYSIZE = Message_DataType_DataType_MAX + 1;
+
+enum Message_Prop {
+  Message_Prop_CaptureDraw = 0,
+  Message_Prop_TimeMode = 1,
+  Message_Prop_ExpectResponse = 2,
+  Message_Prop_CaptureSwap = 3,
+  Message_Prop_GLConstant = 4
+};
+bool Message_Prop_IsValid(int value);
+const Message_Prop Message_Prop_Prop_MIN = Message_Prop_CaptureDraw;
+const Message_Prop Message_Prop_Prop_MAX = Message_Prop_GLConstant;
+const int Message_Prop_Prop_ARRAYSIZE = Message_Prop_Prop_MAX + 1;
+
+// ===================================================================
+
+class Message : public ::google::protobuf::MessageLite {
+ public:
+  Message();
+  virtual ~Message();
+  
+  Message(const Message& from);
+  
+  inline Message& operator=(const Message& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  static const Message& default_instance();
+  
+  void Swap(Message* other);
+  
+  // implements Message ----------------------------------------------
+  
+  Message* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const Message& from);
+  void MergeFrom(const Message& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::std::string GetTypeName() const;
+  
+  // nested types ----------------------------------------------------
+  
+  typedef Message_Function Function;
+  static const Function glActiveTexture = Message_Function_glActiveTexture;
+  static const Function glAttachShader = Message_Function_glAttachShader;
+  static const Function glBindAttribLocation = Message_Function_glBindAttribLocation;
+  static const Function glBindBuffer = Message_Function_glBindBuffer;
+  static const Function glBindFramebuffer = Message_Function_glBindFramebuffer;
+  static const Function glBindRenderbuffer = Message_Function_glBindRenderbuffer;
+  static const Function glBindTexture = Message_Function_glBindTexture;
+  static const Function glBlendColor = Message_Function_glBlendColor;
+  static const Function glBlendEquation = Message_Function_glBlendEquation;
+  static const Function glBlendEquationSeparate = Message_Function_glBlendEquationSeparate;
+  static const Function glBlendFunc = Message_Function_glBlendFunc;
+  static const Function glBlendFuncSeparate = Message_Function_glBlendFuncSeparate;
+  static const Function glBufferData = Message_Function_glBufferData;
+  static const Function glBufferSubData = Message_Function_glBufferSubData;
+  static const Function glCheckFramebufferStatus = Message_Function_glCheckFramebufferStatus;
+  static const Function glClear = Message_Function_glClear;
+  static const Function glClearColor = Message_Function_glClearColor;
+  static const Function glClearDepthf = Message_Function_glClearDepthf;
+  static const Function glClearStencil = Message_Function_glClearStencil;
+  static const Function glColorMask = Message_Function_glColorMask;
+  static const Function glCompileShader = Message_Function_glCompileShader;
+  static const Function glCompressedTexImage2D = Message_Function_glCompressedTexImage2D;
+  static const Function glCompressedTexSubImage2D = Message_Function_glCompressedTexSubImage2D;
+  static const Function glCopyTexImage2D = Message_Function_glCopyTexImage2D;
+  static const Function glCopyTexSubImage2D = Message_Function_glCopyTexSubImage2D;
+  static const Function glCreateProgram = Message_Function_glCreateProgram;
+  static const Function glCreateShader = Message_Function_glCreateShader;
+  static const Function glCullFace = Message_Function_glCullFace;
+  static const Function glDeleteBuffers = Message_Function_glDeleteBuffers;
+  static const Function glDeleteFramebuffers = Message_Function_glDeleteFramebuffers;
+  static const Function glDeleteProgram = Message_Function_glDeleteProgram;
+  static const Function glDeleteRenderbuffers = Message_Function_glDeleteRenderbuffers;
+  static const Function glDeleteShader = Message_Function_glDeleteShader;
+  static const Function glDeleteTextures = Message_Function_glDeleteTextures;
+  static const Function glDepthFunc = Message_Function_glDepthFunc;
+  static const Function glDepthMask = Message_Function_glDepthMask;
+  static const Function glDepthRangef = Message_Function_glDepthRangef;
+  static const Function glDetachShader = Message_Function_glDetachShader;
+  static const Function glDisable = Message_Function_glDisable;
+  static const Function glDisableVertexAttribArray = Message_Function_glDisableVertexAttribArray;
+  static const Function glDrawArrays = Message_Function_glDrawArrays;
+  static const Function glDrawElements = Message_Function_glDrawElements;
+  static const Function glEnable = Message_Function_glEnable;
+  static const Function glEnableVertexAttribArray = Message_Function_glEnableVertexAttribArray;
+  static const Function glFinish = Message_Function_glFinish;
+  static const Function glFlush = Message_Function_glFlush;
+  static const Function glFramebufferRenderbuffer = Message_Function_glFramebufferRenderbuffer;
+  static const Function glFramebufferTexture2D = Message_Function_glFramebufferTexture2D;
+  static const Function glFrontFace = Message_Function_glFrontFace;
+  static const Function glGenBuffers = Message_Function_glGenBuffers;
+  static const Function glGenerateMipmap = Message_Function_glGenerateMipmap;
+  static const Function glGenFramebuffers = Message_Function_glGenFramebuffers;
+  static const Function glGenRenderbuffers = Message_Function_glGenRenderbuffers;
+  static const Function glGenTextures = Message_Function_glGenTextures;
+  static const Function glGetActiveAttrib = Message_Function_glGetActiveAttrib;
+  static const Function glGetActiveUniform = Message_Function_glGetActiveUniform;
+  static const Function glGetAttachedShaders = Message_Function_glGetAttachedShaders;
+  static const Function glGetAttribLocation = Message_Function_glGetAttribLocation;
+  static const Function glGetBooleanv = Message_Function_glGetBooleanv;
+  static const Function glGetBufferParameteriv = Message_Function_glGetBufferParameteriv;
+  static const Function glGetError = Message_Function_glGetError;
+  static const Function glGetFloatv = Message_Function_glGetFloatv;
+  static const Function glGetFramebufferAttachmentParameteriv = Message_Function_glGetFramebufferAttachmentParameteriv;
+  static const Function glGetIntegerv = Message_Function_glGetIntegerv;
+  static const Function glGetProgramiv = Message_Function_glGetProgramiv;
+  static const Function glGetProgramInfoLog = Message_Function_glGetProgramInfoLog;
+  static const Function glGetRenderbufferParameteriv = Message_Function_glGetRenderbufferParameteriv;
+  static const Function glGetShaderiv = Message_Function_glGetShaderiv;
+  static const Function glGetShaderInfoLog = Message_Function_glGetShaderInfoLog;
+  static const Function glGetShaderPrecisionFormat = Message_Function_glGetShaderPrecisionFormat;
+  static const Function glGetShaderSource = Message_Function_glGetShaderSource;
+  static const Function glGetString = Message_Function_glGetString;
+  static const Function glGetTexParameterfv = Message_Function_glGetTexParameterfv;
+  static const Function glGetTexParameteriv = Message_Function_glGetTexParameteriv;
+  static const Function glGetUniformfv = Message_Function_glGetUniformfv;
+  static const Function glGetUniformiv = Message_Function_glGetUniformiv;
+  static const Function glGetUniformLocation = Message_Function_glGetUniformLocation;
+  static const Function glGetVertexAttribfv = Message_Function_glGetVertexAttribfv;
+  static const Function glGetVertexAttribiv = Message_Function_glGetVertexAttribiv;
+  static const Function glGetVertexAttribPointerv = Message_Function_glGetVertexAttribPointerv;
+  static const Function glHint = Message_Function_glHint;
+  static const Function glIsBuffer = Message_Function_glIsBuffer;
+  static const Function glIsEnabled = Message_Function_glIsEnabled;
+  static const Function glIsFramebuffer = Message_Function_glIsFramebuffer;
+  static const Function glIsProgram = Message_Function_glIsProgram;
+  static const Function glIsRenderbuffer = Message_Function_glIsRenderbuffer;
+  static const Function glIsShader = Message_Function_glIsShader;
+  static const Function glIsTexture = Message_Function_glIsTexture;
+  static const Function glLineWidth = Message_Function_glLineWidth;
+  static const Function glLinkProgram = Message_Function_glLinkProgram;
+  static const Function glPixelStorei = Message_Function_glPixelStorei;
+  static const Function glPolygonOffset = Message_Function_glPolygonOffset;
+  static const Function glReadPixels = Message_Function_glReadPixels;
+  static const Function glReleaseShaderCompiler = Message_Function_glReleaseShaderCompiler;
+  static const Function glRenderbufferStorage = Message_Function_glRenderbufferStorage;
+  static const Function glSampleCoverage = Message_Function_glSampleCoverage;
+  static const Function glScissor = Message_Function_glScissor;
+  static const Function glShaderBinary = Message_Function_glShaderBinary;
+  static const Function glShaderSource = Message_Function_glShaderSource;
+  static const Function glStencilFunc = Message_Function_glStencilFunc;
+  static const Function glStencilFuncSeparate = Message_Function_glStencilFuncSeparate;
+  static const Function glStencilMask = Message_Function_glStencilMask;
+  static const Function glStencilMaskSeparate = Message_Function_glStencilMaskSeparate;
+  static const Function glStencilOp = Message_Function_glStencilOp;
+  static const Function glStencilOpSeparate = Message_Function_glStencilOpSeparate;
+  static const Function glTexImage2D = Message_Function_glTexImage2D;
+  static const Function glTexParameterf = Message_Function_glTexParameterf;
+  static const Function glTexParameterfv = Message_Function_glTexParameterfv;
+  static const Function glTexParameteri = Message_Function_glTexParameteri;
+  static const Function glTexParameteriv = Message_Function_glTexParameteriv;
+  static const Function glTexSubImage2D = Message_Function_glTexSubImage2D;
+  static const Function glUniform1f = Message_Function_glUniform1f;
+  static const Function glUniform1fv = Message_Function_glUniform1fv;
+  static const Function glUniform1i = Message_Function_glUniform1i;
+  static const Function glUniform1iv = Message_Function_glUniform1iv;
+  static const Function glUniform2f = Message_Function_glUniform2f;
+  static const Function glUniform2fv = Message_Function_glUniform2fv;
+  static const Function glUniform2i = Message_Function_glUniform2i;
+  static const Function glUniform2iv = Message_Function_glUniform2iv;
+  static const Function glUniform3f = Message_Function_glUniform3f;
+  static const Function glUniform3fv = Message_Function_glUniform3fv;
+  static const Function glUniform3i = Message_Function_glUniform3i;
+  static const Function glUniform3iv = Message_Function_glUniform3iv;
+  static const Function glUniform4f = Message_Function_glUniform4f;
+  static const Function glUniform4fv = Message_Function_glUniform4fv;
+  static const Function glUniform4i = Message_Function_glUniform4i;
+  static const Function glUniform4iv = Message_Function_glUniform4iv;
+  static const Function glUniformMatrix2fv = Message_Function_glUniformMatrix2fv;
+  static const Function glUniformMatrix3fv = Message_Function_glUniformMatrix3fv;
+  static const Function glUniformMatrix4fv = Message_Function_glUniformMatrix4fv;
+  static const Function glUseProgram = Message_Function_glUseProgram;
+  static const Function glValidateProgram = Message_Function_glValidateProgram;
+  static const Function glVertexAttrib1f = Message_Function_glVertexAttrib1f;
+  static const Function glVertexAttrib1fv = Message_Function_glVertexAttrib1fv;
+  static const Function glVertexAttrib2f = Message_Function_glVertexAttrib2f;
+  static const Function glVertexAttrib2fv = Message_Function_glVertexAttrib2fv;
+  static const Function glVertexAttrib3f = Message_Function_glVertexAttrib3f;
+  static const Function glVertexAttrib3fv = Message_Function_glVertexAttrib3fv;
+  static const Function glVertexAttrib4f = Message_Function_glVertexAttrib4f;
+  static const Function glVertexAttrib4fv = Message_Function_glVertexAttrib4fv;
+  static const Function glVertexAttribPointer = Message_Function_glVertexAttribPointer;
+  static const Function glViewport = Message_Function_glViewport;
+  static const Function eglGetDisplay = Message_Function_eglGetDisplay;
+  static const Function eglInitialize = Message_Function_eglInitialize;
+  static const Function eglTerminate = Message_Function_eglTerminate;
+  static const Function eglGetConfigs = Message_Function_eglGetConfigs;
+  static const Function eglChooseConfig = Message_Function_eglChooseConfig;
+  static const Function eglGetConfigAttrib = Message_Function_eglGetConfigAttrib;
+  static const Function eglCreateWindowSurface = Message_Function_eglCreateWindowSurface;
+  static const Function eglCreatePixmapSurface = Message_Function_eglCreatePixmapSurface;
+  static const Function eglCreatePbufferSurface = Message_Function_eglCreatePbufferSurface;
+  static const Function eglDestroySurface = Message_Function_eglDestroySurface;
+  static const Function eglQuerySurface = Message_Function_eglQuerySurface;
+  static const Function eglCreateContext = Message_Function_eglCreateContext;
+  static const Function eglDestroyContext = Message_Function_eglDestroyContext;
+  static const Function eglMakeCurrent = Message_Function_eglMakeCurrent;
+  static const Function eglGetCurrentContext = Message_Function_eglGetCurrentContext;
+  static const Function eglGetCurrentSurface = Message_Function_eglGetCurrentSurface;
+  static const Function eglGetCurrentDisplay = Message_Function_eglGetCurrentDisplay;
+  static const Function eglQueryContext = Message_Function_eglQueryContext;
+  static const Function eglWaitGL = Message_Function_eglWaitGL;
+  static const Function eglWaitNative = Message_Function_eglWaitNative;
+  static const Function eglSwapBuffers = Message_Function_eglSwapBuffers;
+  static const Function eglCopyBuffers = Message_Function_eglCopyBuffers;
+  static const Function eglGetError = Message_Function_eglGetError;
+  static const Function eglQueryString = Message_Function_eglQueryString;
+  static const Function eglGetProcAddress = Message_Function_eglGetProcAddress;
+  static const Function eglSurfaceAttrib = Message_Function_eglSurfaceAttrib;
+  static const Function eglBindTexImage = Message_Function_eglBindTexImage;
+  static const Function eglReleaseTexImage = Message_Function_eglReleaseTexImage;
+  static const Function eglSwapInterval = Message_Function_eglSwapInterval;
+  static const Function eglBindAPI = Message_Function_eglBindAPI;
+  static const Function eglQueryAPI = Message_Function_eglQueryAPI;
+  static const Function eglWaitClient = Message_Function_eglWaitClient;
+  static const Function eglReleaseThread = Message_Function_eglReleaseThread;
+  static const Function eglCreatePbufferFromClientBuffer = Message_Function_eglCreatePbufferFromClientBuffer;
+  static const Function eglLockSurfaceKHR = Message_Function_eglLockSurfaceKHR;
+  static const Function eglUnlockSurfaceKHR = Message_Function_eglUnlockSurfaceKHR;
+  static const Function eglCreateImageKHR = Message_Function_eglCreateImageKHR;
+  static const Function eglDestroyImageKHR = Message_Function_eglDestroyImageKHR;
+  static const Function eglCreateSyncKHR = Message_Function_eglCreateSyncKHR;
+  static const Function eglDestroySyncKHR = Message_Function_eglDestroySyncKHR;
+  static const Function eglClientWaitSyncKHR = Message_Function_eglClientWaitSyncKHR;
+  static const Function eglGetSyncAttribKHR = Message_Function_eglGetSyncAttribKHR;
+  static const Function eglSetSwapRectangleANDROID = Message_Function_eglSetSwapRectangleANDROID;
+  static const Function eglGetRenderBufferANDROID = Message_Function_eglGetRenderBufferANDROID;
+  static const Function ACK = Message_Function_ACK;
+  static const Function NEG = Message_Function_NEG;
+  static const Function CONTINUE = Message_Function_CONTINUE;
+  static const Function SKIP = Message_Function_SKIP;
+  static const Function SETPROP = Message_Function_SETPROP;
+  static inline bool Function_IsValid(int value) {
+    return Message_Function_IsValid(value);
+  }
+  static const Function Function_MIN =
+    Message_Function_Function_MIN;
+  static const Function Function_MAX =
+    Message_Function_Function_MAX;
+  static const int Function_ARRAYSIZE =
+    Message_Function_Function_ARRAYSIZE;
+  
+  typedef Message_Type Type;
+  static const Type BeforeCall = Message_Type_BeforeCall;
+  static const Type AfterCall = Message_Type_AfterCall;
+  static const Type AfterGeneratedCall = Message_Type_AfterGeneratedCall;
+  static const Type Response = Message_Type_Response;
+  static const Type CompleteCall = Message_Type_CompleteCall;
+  static inline bool Type_IsValid(int value) {
+    return Message_Type_IsValid(value);
+  }
+  static const Type Type_MIN =
+    Message_Type_Type_MIN;
+  static const Type Type_MAX =
+    Message_Type_Type_MAX;
+  static const int Type_ARRAYSIZE =
+    Message_Type_Type_ARRAYSIZE;
+  
+  typedef Message_DataType DataType;
+  static const DataType ReferencedImage = Message_DataType_ReferencedImage;
+  static const DataType NonreferencedImage = Message_DataType_NonreferencedImage;
+  static inline bool DataType_IsValid(int value) {
+    return Message_DataType_IsValid(value);
+  }
+  static const DataType DataType_MIN =
+    Message_DataType_DataType_MIN;
+  static const DataType DataType_MAX =
+    Message_DataType_DataType_MAX;
+  static const int DataType_ARRAYSIZE =
+    Message_DataType_DataType_ARRAYSIZE;
+  
+  typedef Message_Prop Prop;
+  static const Prop CaptureDraw = Message_Prop_CaptureDraw;
+  static const Prop TimeMode = Message_Prop_TimeMode;
+  static const Prop ExpectResponse = Message_Prop_ExpectResponse;
+  static const Prop CaptureSwap = Message_Prop_CaptureSwap;
+  static const Prop GLConstant = Message_Prop_GLConstant;
+  static inline bool Prop_IsValid(int value) {
+    return Message_Prop_IsValid(value);
+  }
+  static const Prop Prop_MIN =
+    Message_Prop_Prop_MIN;
+  static const Prop Prop_MAX =
+    Message_Prop_Prop_MAX;
+  static const int Prop_ARRAYSIZE =
+    Message_Prop_Prop_ARRAYSIZE;
+  
+  // accessors -------------------------------------------------------
+  
+  // required int32 context_id = 1;
+  inline bool has_context_id() const;
+  inline void clear_context_id();
+  static const int kContextIdFieldNumber = 1;
+  inline ::google::protobuf::int32 context_id() const;
+  inline void set_context_id(::google::protobuf::int32 value);
+  
+  // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+  inline bool has_function() const;
+  inline void clear_function();
+  static const int kFunctionFieldNumber = 2;
+  inline ::com::android::glesv2debugger::Message_Function function() const;
+  inline void set_function(::com::android::glesv2debugger::Message_Function value);
+  
+  // required .com.android.glesv2debugger.Message.Type type = 3;
+  inline bool has_type() const;
+  inline void clear_type();
+  static const int kTypeFieldNumber = 3;
+  inline ::com::android::glesv2debugger::Message_Type type() const;
+  inline void set_type(::com::android::glesv2debugger::Message_Type value);
+  
+  // required bool expect_response = 4;
+  inline bool has_expect_response() const;
+  inline void clear_expect_response();
+  static const int kExpectResponseFieldNumber = 4;
+  inline bool expect_response() const;
+  inline void set_expect_response(bool value);
+  
+  // optional int32 ret = 5;
+  inline bool has_ret() const;
+  inline void clear_ret();
+  static const int kRetFieldNumber = 5;
+  inline ::google::protobuf::int32 ret() const;
+  inline void set_ret(::google::protobuf::int32 value);
+  
+  // optional int32 arg0 = 6;
+  inline bool has_arg0() const;
+  inline void clear_arg0();
+  static const int kArg0FieldNumber = 6;
+  inline ::google::protobuf::int32 arg0() const;
+  inline void set_arg0(::google::protobuf::int32 value);
+  
+  // optional int32 arg1 = 7;
+  inline bool has_arg1() const;
+  inline void clear_arg1();
+  static const int kArg1FieldNumber = 7;
+  inline ::google::protobuf::int32 arg1() const;
+  inline void set_arg1(::google::protobuf::int32 value);
+  
+  // optional int32 arg2 = 8;
+  inline bool has_arg2() const;
+  inline void clear_arg2();
+  static const int kArg2FieldNumber = 8;
+  inline ::google::protobuf::int32 arg2() const;
+  inline void set_arg2(::google::protobuf::int32 value);
+  
+  // optional int32 arg3 = 9;
+  inline bool has_arg3() const;
+  inline void clear_arg3();
+  static const int kArg3FieldNumber = 9;
+  inline ::google::protobuf::int32 arg3() const;
+  inline void set_arg3(::google::protobuf::int32 value);
+  
+  // optional int32 arg4 = 16;
+  inline bool has_arg4() const;
+  inline void clear_arg4();
+  static const int kArg4FieldNumber = 16;
+  inline ::google::protobuf::int32 arg4() const;
+  inline void set_arg4(::google::protobuf::int32 value);
+  
+  // optional int32 arg5 = 17;
+  inline bool has_arg5() const;
+  inline void clear_arg5();
+  static const int kArg5FieldNumber = 17;
+  inline ::google::protobuf::int32 arg5() const;
+  inline void set_arg5(::google::protobuf::int32 value);
+  
+  // optional int32 arg6 = 18;
+  inline bool has_arg6() const;
+  inline void clear_arg6();
+  static const int kArg6FieldNumber = 18;
+  inline ::google::protobuf::int32 arg6() const;
+  inline void set_arg6(::google::protobuf::int32 value);
+  
+  // optional int32 arg7 = 19;
+  inline bool has_arg7() const;
+  inline void clear_arg7();
+  static const int kArg7FieldNumber = 19;
+  inline ::google::protobuf::int32 arg7() const;
+  inline void set_arg7(::google::protobuf::int32 value);
+  
+  // optional int32 arg8 = 20;
+  inline bool has_arg8() const;
+  inline void clear_arg8();
+  static const int kArg8FieldNumber = 20;
+  inline ::google::protobuf::int32 arg8() const;
+  inline void set_arg8(::google::protobuf::int32 value);
+  
+  // optional bytes data = 10;
+  inline bool has_data() const;
+  inline void clear_data();
+  static const int kDataFieldNumber = 10;
+  inline const ::std::string& data() const;
+  inline void set_data(const ::std::string& value);
+  inline void set_data(const char* value);
+  inline void set_data(const void* value, size_t size);
+  inline ::std::string* mutable_data();
+  
+  // optional .com.android.glesv2debugger.Message.DataType data_type = 23;
+  inline bool has_data_type() const;
+  inline void clear_data_type();
+  static const int kDataTypeFieldNumber = 23;
+  inline ::com::android::glesv2debugger::Message_DataType data_type() const;
+  inline void set_data_type(::com::android::glesv2debugger::Message_DataType value);
+  
+  // optional int32 pixel_format = 24;
+  inline bool has_pixel_format() const;
+  inline void clear_pixel_format();
+  static const int kPixelFormatFieldNumber = 24;
+  inline ::google::protobuf::int32 pixel_format() const;
+  inline void set_pixel_format(::google::protobuf::int32 value);
+  
+  // optional int32 pixel_type = 25;
+  inline bool has_pixel_type() const;
+  inline void clear_pixel_type();
+  static const int kPixelTypeFieldNumber = 25;
+  inline ::google::protobuf::int32 pixel_type() const;
+  inline void set_pixel_type(::google::protobuf::int32 value);
+  
+  // optional int32 image_width = 26;
+  inline bool has_image_width() const;
+  inline void clear_image_width();
+  static const int kImageWidthFieldNumber = 26;
+  inline ::google::protobuf::int32 image_width() const;
+  inline void set_image_width(::google::protobuf::int32 value);
+  
+  // optional int32 image_height = 27;
+  inline bool has_image_height() const;
+  inline void clear_image_height();
+  static const int kImageHeightFieldNumber = 27;
+  inline ::google::protobuf::int32 image_height() const;
+  inline void set_image_height(::google::protobuf::int32 value);
+  
+  // optional float time = 11;
+  inline bool has_time() const;
+  inline void clear_time();
+  static const int kTimeFieldNumber = 11;
+  inline float time() const;
+  inline void set_time(float value);
+  
+  // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+  inline bool has_prop() const;
+  inline void clear_prop();
+  static const int kPropFieldNumber = 21;
+  inline ::com::android::glesv2debugger::Message_Prop prop() const;
+  inline void set_prop(::com::android::glesv2debugger::Message_Prop value);
+  
+  // optional float clock = 22;
+  inline bool has_clock() const;
+  inline void clear_clock();
+  static const int kClockFieldNumber = 22;
+  inline float clock() const;
+  inline void set_clock(float value);
+  
+  // @@protoc_insertion_point(class_scope:com.android.glesv2debugger.Message)
+ private:
+  mutable int _cached_size_;
+  
+  ::google::protobuf::int32 context_id_;
+  int function_;
+  int type_;
+  bool expect_response_;
+  ::google::protobuf::int32 ret_;
+  ::google::protobuf::int32 arg0_;
+  ::google::protobuf::int32 arg1_;
+  ::google::protobuf::int32 arg2_;
+  ::google::protobuf::int32 arg3_;
+  ::google::protobuf::int32 arg4_;
+  ::google::protobuf::int32 arg5_;
+  ::google::protobuf::int32 arg6_;
+  ::google::protobuf::int32 arg7_;
+  ::google::protobuf::int32 arg8_;
+  ::std::string* data_;
+  static const ::std::string _default_data_;
+  int data_type_;
+  ::google::protobuf::int32 pixel_format_;
+  ::google::protobuf::int32 pixel_type_;
+  ::google::protobuf::int32 image_width_;
+  ::google::protobuf::int32 image_height_;
+  float time_;
+  int prop_;
+  float clock_;
+  friend void  protobuf_AddDesc_debugger_5fmessage_2eproto();
+  friend void protobuf_AssignDesc_debugger_5fmessage_2eproto();
+  friend void protobuf_ShutdownFile_debugger_5fmessage_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(23 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static Message* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+// Message
+
+// required int32 context_id = 1;
+inline bool Message::has_context_id() const {
+  return _has_bit(0);
+}
+inline void Message::clear_context_id() {
+  context_id_ = 0;
+  _clear_bit(0);
+}
+inline ::google::protobuf::int32 Message::context_id() const {
+  return context_id_;
+}
+inline void Message::set_context_id(::google::protobuf::int32 value) {
+  _set_bit(0);
+  context_id_ = value;
+}
+
+// required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+inline bool Message::has_function() const {
+  return _has_bit(1);
+}
+inline void Message::clear_function() {
+  function_ = 187;
+  _clear_bit(1);
+}
+inline ::com::android::glesv2debugger::Message_Function Message::function() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Function >(function_);
+}
+inline void Message::set_function(::com::android::glesv2debugger::Message_Function value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Function_IsValid(value));
+  _set_bit(1);
+  function_ = value;
+}
+
+// required .com.android.glesv2debugger.Message.Type type = 3;
+inline bool Message::has_type() const {
+  return _has_bit(2);
+}
+inline void Message::clear_type() {
+  type_ = 0;
+  _clear_bit(2);
+}
+inline ::com::android::glesv2debugger::Message_Type Message::type() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Type >(type_);
+}
+inline void Message::set_type(::com::android::glesv2debugger::Message_Type value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Type_IsValid(value));
+  _set_bit(2);
+  type_ = value;
+}
+
+// required bool expect_response = 4;
+inline bool Message::has_expect_response() const {
+  return _has_bit(3);
+}
+inline void Message::clear_expect_response() {
+  expect_response_ = false;
+  _clear_bit(3);
+}
+inline bool Message::expect_response() const {
+  return expect_response_;
+}
+inline void Message::set_expect_response(bool value) {
+  _set_bit(3);
+  expect_response_ = value;
+}
+
+// optional int32 ret = 5;
+inline bool Message::has_ret() const {
+  return _has_bit(4);
+}
+inline void Message::clear_ret() {
+  ret_ = 0;
+  _clear_bit(4);
+}
+inline ::google::protobuf::int32 Message::ret() const {
+  return ret_;
+}
+inline void Message::set_ret(::google::protobuf::int32 value) {
+  _set_bit(4);
+  ret_ = value;
+}
+
+// optional int32 arg0 = 6;
+inline bool Message::has_arg0() const {
+  return _has_bit(5);
+}
+inline void Message::clear_arg0() {
+  arg0_ = 0;
+  _clear_bit(5);
+}
+inline ::google::protobuf::int32 Message::arg0() const {
+  return arg0_;
+}
+inline void Message::set_arg0(::google::protobuf::int32 value) {
+  _set_bit(5);
+  arg0_ = value;
+}
+
+// optional int32 arg1 = 7;
+inline bool Message::has_arg1() const {
+  return _has_bit(6);
+}
+inline void Message::clear_arg1() {
+  arg1_ = 0;
+  _clear_bit(6);
+}
+inline ::google::protobuf::int32 Message::arg1() const {
+  return arg1_;
+}
+inline void Message::set_arg1(::google::protobuf::int32 value) {
+  _set_bit(6);
+  arg1_ = value;
+}
+
+// optional int32 arg2 = 8;
+inline bool Message::has_arg2() const {
+  return _has_bit(7);
+}
+inline void Message::clear_arg2() {
+  arg2_ = 0;
+  _clear_bit(7);
+}
+inline ::google::protobuf::int32 Message::arg2() const {
+  return arg2_;
+}
+inline void Message::set_arg2(::google::protobuf::int32 value) {
+  _set_bit(7);
+  arg2_ = value;
+}
+
+// optional int32 arg3 = 9;
+inline bool Message::has_arg3() const {
+  return _has_bit(8);
+}
+inline void Message::clear_arg3() {
+  arg3_ = 0;
+  _clear_bit(8);
+}
+inline ::google::protobuf::int32 Message::arg3() const {
+  return arg3_;
+}
+inline void Message::set_arg3(::google::protobuf::int32 value) {
+  _set_bit(8);
+  arg3_ = value;
+}
+
+// optional int32 arg4 = 16;
+inline bool Message::has_arg4() const {
+  return _has_bit(9);
+}
+inline void Message::clear_arg4() {
+  arg4_ = 0;
+  _clear_bit(9);
+}
+inline ::google::protobuf::int32 Message::arg4() const {
+  return arg4_;
+}
+inline void Message::set_arg4(::google::protobuf::int32 value) {
+  _set_bit(9);
+  arg4_ = value;
+}
+
+// optional int32 arg5 = 17;
+inline bool Message::has_arg5() const {
+  return _has_bit(10);
+}
+inline void Message::clear_arg5() {
+  arg5_ = 0;
+  _clear_bit(10);
+}
+inline ::google::protobuf::int32 Message::arg5() const {
+  return arg5_;
+}
+inline void Message::set_arg5(::google::protobuf::int32 value) {
+  _set_bit(10);
+  arg5_ = value;
+}
+
+// optional int32 arg6 = 18;
+inline bool Message::has_arg6() const {
+  return _has_bit(11);
+}
+inline void Message::clear_arg6() {
+  arg6_ = 0;
+  _clear_bit(11);
+}
+inline ::google::protobuf::int32 Message::arg6() const {
+  return arg6_;
+}
+inline void Message::set_arg6(::google::protobuf::int32 value) {
+  _set_bit(11);
+  arg6_ = value;
+}
+
+// optional int32 arg7 = 19;
+inline bool Message::has_arg7() const {
+  return _has_bit(12);
+}
+inline void Message::clear_arg7() {
+  arg7_ = 0;
+  _clear_bit(12);
+}
+inline ::google::protobuf::int32 Message::arg7() const {
+  return arg7_;
+}
+inline void Message::set_arg7(::google::protobuf::int32 value) {
+  _set_bit(12);
+  arg7_ = value;
+}
+
+// optional int32 arg8 = 20;
+inline bool Message::has_arg8() const {
+  return _has_bit(13);
+}
+inline void Message::clear_arg8() {
+  arg8_ = 0;
+  _clear_bit(13);
+}
+inline ::google::protobuf::int32 Message::arg8() const {
+  return arg8_;
+}
+inline void Message::set_arg8(::google::protobuf::int32 value) {
+  _set_bit(13);
+  arg8_ = value;
+}
+
+// optional bytes data = 10;
+inline bool Message::has_data() const {
+  return _has_bit(14);
+}
+inline void Message::clear_data() {
+  if (data_ != &_default_data_) {
+    data_->clear();
+  }
+  _clear_bit(14);
+}
+inline const ::std::string& Message::data() const {
+  return *data_;
+}
+inline void Message::set_data(const ::std::string& value) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+}
+inline void Message::set_data(const char* value) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+}
+inline void Message::set_data(const void* value, size_t size) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* Message::mutable_data() {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  return data_;
+}
+
+// optional .com.android.glesv2debugger.Message.DataType data_type = 23;
+inline bool Message::has_data_type() const {
+  return _has_bit(15);
+}
+inline void Message::clear_data_type() {
+  data_type_ = 0;
+  _clear_bit(15);
+}
+inline ::com::android::glesv2debugger::Message_DataType Message::data_type() const {
+  return static_cast< ::com::android::glesv2debugger::Message_DataType >(data_type_);
+}
+inline void Message::set_data_type(::com::android::glesv2debugger::Message_DataType value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_DataType_IsValid(value));
+  _set_bit(15);
+  data_type_ = value;
+}
+
+// optional int32 pixel_format = 24;
+inline bool Message::has_pixel_format() const {
+  return _has_bit(16);
+}
+inline void Message::clear_pixel_format() {
+  pixel_format_ = 0;
+  _clear_bit(16);
+}
+inline ::google::protobuf::int32 Message::pixel_format() const {
+  return pixel_format_;
+}
+inline void Message::set_pixel_format(::google::protobuf::int32 value) {
+  _set_bit(16);
+  pixel_format_ = value;
+}
+
+// optional int32 pixel_type = 25;
+inline bool Message::has_pixel_type() const {
+  return _has_bit(17);
+}
+inline void Message::clear_pixel_type() {
+  pixel_type_ = 0;
+  _clear_bit(17);
+}
+inline ::google::protobuf::int32 Message::pixel_type() const {
+  return pixel_type_;
+}
+inline void Message::set_pixel_type(::google::protobuf::int32 value) {
+  _set_bit(17);
+  pixel_type_ = value;
+}
+
+// optional int32 image_width = 26;
+inline bool Message::has_image_width() const {
+  return _has_bit(18);
+}
+inline void Message::clear_image_width() {
+  image_width_ = 0;
+  _clear_bit(18);
+}
+inline ::google::protobuf::int32 Message::image_width() const {
+  return image_width_;
+}
+inline void Message::set_image_width(::google::protobuf::int32 value) {
+  _set_bit(18);
+  image_width_ = value;
+}
+
+// optional int32 image_height = 27;
+inline bool Message::has_image_height() const {
+  return _has_bit(19);
+}
+inline void Message::clear_image_height() {
+  image_height_ = 0;
+  _clear_bit(19);
+}
+inline ::google::protobuf::int32 Message::image_height() const {
+  return image_height_;
+}
+inline void Message::set_image_height(::google::protobuf::int32 value) {
+  _set_bit(19);
+  image_height_ = value;
+}
+
+// optional float time = 11;
+inline bool Message::has_time() const {
+  return _has_bit(20);
+}
+inline void Message::clear_time() {
+  time_ = 0;
+  _clear_bit(20);
+}
+inline float Message::time() const {
+  return time_;
+}
+inline void Message::set_time(float value) {
+  _set_bit(20);
+  time_ = value;
+}
+
+// optional .com.android.glesv2debugger.Message.Prop prop = 21;
+inline bool Message::has_prop() const {
+  return _has_bit(21);
+}
+inline void Message::clear_prop() {
+  prop_ = 0;
+  _clear_bit(21);
+}
+inline ::com::android::glesv2debugger::Message_Prop Message::prop() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Prop >(prop_);
+}
+inline void Message::set_prop(::com::android::glesv2debugger::Message_Prop value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Prop_IsValid(value));
+  _set_bit(21);
+  prop_ = value;
+}
+
+// optional float clock = 22;
+inline bool Message::has_clock() const {
+  return _has_bit(22);
+}
+inline void Message::clear_clock() {
+  clock_ = 0;
+  _clear_bit(22);
+}
+inline float Message::clock() const {
+  return clock_;
+}
+inline void Message::set_clock(float value) {
+  _set_bit(22);
+  clock_ = value;
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace glesv2debugger
+}  // namespace android
+}  // namespace com
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
diff --git a/opengl/libs/GLES2_dbg/src/egl.cpp b/opengl/libs/GLES2_dbg/src/egl.cpp
new file mode 100644
index 0000000..eb28d06
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/egl.cpp
@@ -0,0 +1,54 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "header.h"
+
+EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+{
+    DbgContext * const dbg = getDbgContextThreadSpecific();
+    glesv2debugger::Message msg;
+    struct : public FunctionCall {
+        EGLDisplay dpy;
+        EGLSurface draw;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            msg.set_time(-1);
+            return reinterpret_cast<const int *>(true);
+        }
+    } caller;
+    caller.dpy = dpy;
+    caller.draw = draw;
+
+    msg.set_arg0(reinterpret_cast<int>(dpy));
+    msg.set_arg1(reinterpret_cast<int>(draw));
+    if (dbg->captureSwap > 0) {
+        dbg->captureSwap--;
+        int viewport[4] = {};
+        dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
+        void * pixels = dbg->GetReadPixelsBuffer(viewport[2] * viewport[3] *
+                        dbg->readBytesPerPixel);
+        dbg->hooks->gl.glReadPixels(viewport[0], viewport[1], viewport[2],
+                                    viewport[3], dbg->readFormat, dbg->readType, pixels);
+        dbg->CompressReadPixelBuffer(msg.mutable_data());
+        msg.set_data_type(msg.ReferencedImage);
+        msg.set_pixel_format(dbg->readFormat);
+        msg.set_pixel_type(dbg->readType);
+        msg.set_image_width(viewport[2]);
+        msg.set_image_height(viewport[3]);
+    }
+    int * ret = MessageLoop(caller, msg, glesv2debugger::Message_Function_eglSwapBuffers);
+    return static_cast<EGLBoolean>(reinterpret_cast<int>(ret));
+}
diff --git a/opengl/libs/GLES2_dbg/src/header.h b/opengl/libs/GLES2_dbg/src/header.h
new file mode 100644
index 0000000..f2b1fa6
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/header.h
@@ -0,0 +1,180 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_GLES2_DBG_HEADER_H
+#define ANDROID_GLES2_DBG_HEADER_H
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <cutils/log.h>
+#include <utils/Timers.h>
+
+#include "hooks.h"
+
+#include "glesv2dbg.h"
+
+#define GL_ENTRY(_r, _api, ...) _r Debug_##_api ( __VA_ARGS__ );
+#include "glesv2dbg_functions.h"
+
+#include "debugger_message.pb.h"
+
+using namespace android;
+using namespace com::android;
+
+#ifndef __location__
+#define __HIERALLOC_STRING_0__(s)   #s
+#define __HIERALLOC_STRING_1__(s)   __HIERALLOC_STRING_0__(s)
+#define __HIERALLOC_STRING_2__      __HIERALLOC_STRING_1__(__LINE__)
+#define __location__                __FILE__ ":" __HIERALLOC_STRING_2__
+#endif
+
+#undef assert
+#define assert(expr) if (!(expr)) { LOGD("\n*\n*\n* assert: %s at %s \n*\n*", #expr, __location__); int * x = 0; *x = 5; }
+//#undef LOGD
+//#define LOGD(...)
+
+namespace android
+{
+
+struct GLFunctionBitfield {
+    unsigned char field [24]; // 8 * 24 = 192
+
+    void Bit(const glesv2debugger::Message_Function function, bool bit) {
+        const unsigned byte = function / 8, mask = 1 << (function % 8);
+        if (bit)
+            field[byte] |= mask;
+        else
+            field[byte] &= ~mask;
+    }
+
+    bool Bit(const glesv2debugger::Message_Function function) const {
+        const unsigned byte = function / 8, mask = 1 << (function % 8);
+        return field[byte] & mask;
+    }
+};
+
+struct DbgContext {
+    static const unsigned int LZF_CHUNK_SIZE = 256 * 1024;
+
+private:
+    char * lzf_buf; // malloc / free; for lzf chunk compression and other uses
+
+    // used as buffer and reference frame for ReadPixels; malloc/free
+    unsigned * lzf_ref [2];
+    unsigned lzf_readIndex; // 0 or 1
+    unsigned lzf_refSize, lzf_refBufSize; // bytes
+
+public:
+    const unsigned int version; // 0 is GLES1, 1 is GLES2
+    const gl_hooks_t * const hooks;
+    const unsigned int MAX_VERTEX_ATTRIBS;
+    const GLenum readFormat, readType; // implementation supported glReadPixels
+    const unsigned int readBytesPerPixel;
+
+    unsigned int captureSwap; // number of eglSwapBuffers to glReadPixels
+    unsigned int captureDraw; // number of glDrawArrays/Elements to glReadPixels
+
+    GLFunctionBitfield expectResponse;
+
+    struct VertexAttrib {
+        GLenum type; // element data type
+        unsigned size; // number of data per element
+        unsigned stride; // calculated number of bytes between elements
+        const void * ptr;
+        unsigned elemSize; // calculated number of bytes per element
+        GLuint buffer; // buffer name
+        GLboolean normalized : 1;
+        GLboolean enabled : 1;
+        VertexAttrib() : type(0), size(0), stride(0), ptr(NULL), elemSize(0),
+                buffer(0), normalized(0), enabled(0) {}
+    } * vertexAttribs;
+    bool hasNonVBOAttribs; // whether any enabled vertexAttrib is user pointer
+
+    struct VBO {
+        const GLuint name;
+        const GLenum target;
+        VBO * next;
+        void * data; // malloc/free
+        unsigned size; // in bytes
+        VBO(const GLuint name, const GLenum target, VBO * head) : name(name),
+                target(target), next(head), data(NULL), size(0) {}
+    } * indexBuffers; // linked list of all index buffers
+    VBO * indexBuffer; // currently bound index buffer
+
+    GLuint program;
+    unsigned maxAttrib; // number of slots used by program
+
+    DbgContext(const unsigned version, const gl_hooks_t * const hooks,
+               const unsigned MAX_VERTEX_ATTRIBS, const GLenum readFormat,
+               const GLenum readType);
+    ~DbgContext();
+
+    void Fetch(const unsigned index, std::string * const data) const;
+    void Compress(const void * in_data, unsigned in_len, std::string * const outStr);
+    static unsigned char * Decompress(const void * in, const unsigned int inLen,
+                                      unsigned int * const outLen); // malloc/free
+    void * GetReadPixelsBuffer(const unsigned size);
+    bool IsReadPixelBuffer(const void * const ptr)  {
+        return ptr == lzf_ref[lzf_readIndex];
+    }
+    void CompressReadPixelBuffer(std::string * const outStr);
+    char * GetBuffer(); // allocates lzf_buf if NULL
+    unsigned int GetBufferSize(); // allocates lzf_buf if NULL
+
+    void glUseProgram(GLuint program);
+    void glEnableVertexAttribArray(GLuint index);
+    void glDisableVertexAttribArray(GLuint index);
+    void glVertexAttribPointer(GLuint indx, GLint size, GLenum type,
+                               GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+    void glBindBuffer(GLenum target, GLuint buffer);
+    void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+    void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+    void glDeleteBuffers(GLsizei n, const GLuint *buffers);
+};
+
+DbgContext * getDbgContextThreadSpecific();
+
+struct FunctionCall {
+    virtual const int * operator()(gl_hooks_t::gl_t const * const _c,
+                                   glesv2debugger::Message & msg) = 0;
+    virtual ~FunctionCall() {}
+};
+
+// move these into DbgContext as static
+extern int timeMode; // SYSTEM_TIME_
+
+extern int clientSock, serverSock;
+
+unsigned GetBytesPerPixel(const GLenum format, const GLenum type);
+
+// every Debug_gl* function calls this to send message to client and possibly receive commands
+int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
+                  const glesv2debugger::Message_Function function);
+
+void Receive(glesv2debugger::Message & cmd);
+float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd);
+void SetProp(DbgContext * const dbg, const glesv2debugger::Message & cmd);
+const int * GenerateCall(DbgContext * const dbg, const glesv2debugger::Message & cmd,
+                         glesv2debugger::Message & msg, const int * const prevRet);
+}; // namespace android {
+
+#endif // #ifndef ANDROID_GLES2_DBG_HEADER_H
diff --git a/opengl/libs/GLES2_dbg/src/server.cpp b/opengl/libs/GLES2_dbg/src/server.cpp
new file mode 100644
index 0000000..0c711bf
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/server.cpp
@@ -0,0 +1,312 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+
+#include "header.h"
+
+namespace android
+{
+
+int serverSock = -1, clientSock = -1;
+FILE * file = NULL;
+unsigned int MAX_FILE_SIZE = 0;
+int timeMode = SYSTEM_TIME_THREAD;
+
+static void Die(const char * msg)
+{
+    LOGD("\n*\n*\n* GLESv2_dbg: Die: %s \n*\n*", msg);
+    StopDebugServer();
+    exit(1);
+}
+
+void StartDebugServer(const unsigned short port, const bool forceUseFile,
+                      const unsigned int maxFileSize, const char * const filePath)
+{
+    MAX_FILE_SIZE = maxFileSize;
+
+    LOGD("GLESv2_dbg: StartDebugServer");
+    if (serverSock >= 0 || file)
+        return;
+
+    LOGD("GLESv2_dbg: StartDebugServer create socket");
+    struct sockaddr_in server = {}, client = {};
+
+    /* Create the TCP socket */
+    if (forceUseFile || (serverSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+        file = fopen(filePath, "wb");
+        if (!file)
+            Die("Failed to create socket and file");
+        else
+            return;
+    }
+    /* Construct the server sockaddr_in structure */
+    server.sin_family = AF_INET;                  /* Internet/IP */
+    server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);   /* Incoming addr */
+    server.sin_port = htons(port);       /* server port */
+
+    /* Bind the server socket */
+    socklen_t sizeofSockaddr_in = sizeof(sockaddr_in);
+    if (bind(serverSock, (struct sockaddr *) &server,
+             sizeof(server)) < 0) {
+        Die("Failed to bind the server socket");
+    }
+    /* Listen on the server socket */
+    if (listen(serverSock, 1) < 0) {
+        Die("Failed to listen on server socket");
+    }
+
+    LOGD("server started on %d \n", server.sin_port);
+
+
+    /* Wait for client connection */
+    if ((clientSock =
+                accept(serverSock, (struct sockaddr *) &client,
+                       &sizeofSockaddr_in)) < 0) {
+        Die("Failed to accept client connection");
+    }
+
+    LOGD("Client connected: %s\n", inet_ntoa(client.sin_addr));
+//    fcntl(clientSock, F_SETFL, O_NONBLOCK);
+}
+
+void StopDebugServer()
+{
+    LOGD("GLESv2_dbg: StopDebugServer");
+    if (clientSock > 0) {
+        close(clientSock);
+        clientSock = -1;
+    }
+    if (serverSock > 0) {
+        close(serverSock);
+        serverSock = -1;
+    }
+    if (file) {
+        fclose(file);
+        file = NULL;
+    }
+}
+
+void Receive(glesv2debugger::Message & cmd)
+{
+    if (clientSock < 0)
+        return;
+    unsigned len = 0;
+    int received = recv(clientSock, &len, 4, MSG_WAITALL);
+    if (received < 0)
+        Die("Failed to receive response length");
+    else if (4 != received) {
+        LOGD("received %dB: %.8X", received, len);
+        Die("Received length mismatch, expected 4");
+    }
+    static void * buffer = NULL;
+    static unsigned bufferSize = 0;
+    if (bufferSize < len) {
+        buffer = realloc(buffer, len);
+        assert(buffer);
+        bufferSize = len;
+    }
+    received = recv(clientSock, buffer, len, MSG_WAITALL);
+    if (received < 0)
+        Die("Failed to receive response");
+    else if (len != received)
+        Die("Received length mismatch");
+    cmd.Clear();
+    cmd.ParseFromArray(buffer, len);
+}
+
+bool TryReceive(glesv2debugger::Message & cmd)
+{
+    if (clientSock < 0)
+        return false;
+    fd_set readSet;
+    FD_ZERO(&readSet);
+    FD_SET(clientSock, &readSet);
+    timeval timeout;
+    timeout.tv_sec = timeout.tv_usec = 0;
+
+    int rc = select(clientSock + 1, &readSet, NULL, NULL, &timeout);
+    if (rc < 0)
+        Die("failed to select clientSock");
+
+    bool received = false;
+    if (FD_ISSET(clientSock, &readSet)) {
+        LOGD("TryReceive: avaiable for read");
+        Receive(cmd);
+        return true;
+    }
+    return false;
+}
+
+float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
+{
+    // TODO: use per DbgContext send/receive buffer and async socket
+    //  instead of mutex and blocking io; watch out for large messages
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    struct Autolock {
+        Autolock() {
+            pthread_mutex_lock(&mutex);
+        }
+        ~Autolock() {
+            pthread_mutex_unlock(&mutex);
+        }
+    } autolock;
+
+    if (msg.function() != glesv2debugger::Message_Function_ACK)
+        assert(msg.has_context_id() && msg.context_id() != 0);
+    static std::string str;
+    msg.SerializeToString(&str);
+    const uint32_t len = str.length();
+    if (clientSock < 0) {
+        if (file) {
+            fwrite(&len, sizeof(len), 1, file);
+            fwrite(str.data(), len, 1, file);
+            if (ftell(file) >= MAX_FILE_SIZE) {
+                fclose(file);
+                Die("MAX_FILE_SIZE reached");
+            }
+        }
+        return 0;
+    }
+    int sent = -1;
+    sent = send(clientSock, &len, sizeof(len), 0);
+    if (sent != sizeof(len)) {
+        LOGD("actual sent=%d expected=%d clientSock=%d", sent, sizeof(len), clientSock);
+        Die("Failed to send message length");
+    }
+    nsecs_t c0 = systemTime(timeMode);
+    sent = send(clientSock, str.data(), str.length(), 0);
+    float t = (float)ns2ms(systemTime(timeMode) - c0);
+    if (sent != str.length()) {
+        LOGD("actual sent=%d expected=%d clientSock=%d", sent, str.length(), clientSock);
+        Die("Failed to send message");
+    }
+    // TODO: factor Receive & TryReceive out and into MessageLoop, or add control argument.
+    // mean while, if server is sending a SETPROP then don't try to receive,
+    //  because server will not be processing received command
+    if (msg.function() == msg.SETPROP)
+        return t;
+    // try to receive commands even though not expecting response,
+    //  since client can send SETPROP and other commands anytime
+    if (!msg.expect_response()) {
+        if (TryReceive(cmd)) {
+            if (glesv2debugger::Message_Function_SETPROP == cmd.function())
+                LOGD("Send: TryReceived SETPROP");
+            else
+                LOGD("Send: TryReceived %u", cmd.function());
+        }
+    } else
+        Receive(cmd);
+    return t;
+}
+
+void SetProp(DbgContext * const dbg, const glesv2debugger::Message & cmd)
+{
+    switch (cmd.prop()) {
+    case glesv2debugger::Message_Prop_CaptureDraw:
+        LOGD("SetProp Message_Prop_CaptureDraw %d", cmd.arg0());
+        dbg->captureDraw = cmd.arg0();
+        break;
+    case glesv2debugger::Message_Prop_TimeMode:
+        LOGD("SetProp Message_Prop_TimeMode %d", cmd.arg0());
+        timeMode = cmd.arg0();
+        break;
+    case glesv2debugger::Message_Prop_ExpectResponse:
+        LOGD("SetProp Message_Prop_ExpectResponse %d=%d", cmd.arg0(), cmd.arg1());
+        dbg->expectResponse.Bit((glesv2debugger::Message_Function)cmd.arg0(), cmd.arg1());
+        break;
+    case glesv2debugger::Message_Prop_CaptureSwap:
+        LOGD("SetProp CaptureSwap %d", cmd.arg0());
+        dbg->captureSwap = cmd.arg0();
+        break;
+    default:
+        assert(0);
+    }
+}
+
+int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
+                  const glesv2debugger::Message_Function function)
+{
+    DbgContext * const dbg = getDbgContextThreadSpecific();
+    const int * ret = 0;
+    glesv2debugger::Message cmd;
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
+    bool expectResponse = dbg->expectResponse.Bit(function);
+    msg.set_expect_response(expectResponse);
+    msg.set_function(function);
+
+    // when not exectResponse, set cmd to CONTINUE then SKIP
+    // cmd will be overwritten by received command
+    cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    cmd.set_expect_response(expectResponse);
+    glesv2debugger::Message_Function oldCmd = cmd.function();
+    Send(msg, cmd);
+    expectResponse = cmd.expect_response();
+    while (true) {
+        msg.Clear();
+        nsecs_t c0 = systemTime(timeMode);
+        switch (cmd.function()) {
+        case glesv2debugger::Message_Function_CONTINUE:
+            ret = functionCall(&dbg->hooks->gl, msg);
+            while (GLenum error = dbg->hooks->gl.glGetError())
+                LOGD("Function=%u glGetError() = 0x%.4X", function, error);
+            if (!msg.has_time()) // some has output data copy, so time inside call
+                msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.set_context_id(reinterpret_cast<int>(dbg));
+            msg.set_function(function);
+            msg.set_type(glesv2debugger::Message_Type_AfterCall);
+            msg.set_expect_response(expectResponse);
+            if (!expectResponse) {
+                cmd.set_function(glesv2debugger::Message_Function_SKIP);
+                cmd.set_expect_response(false);
+            }
+            oldCmd = cmd.function();
+            Send(msg, cmd);
+            expectResponse = cmd.expect_response();
+            break;
+        case glesv2debugger::Message_Function_SKIP:
+            return const_cast<int *>(ret);
+        case glesv2debugger::Message_Function_SETPROP:
+            SetProp(dbg, cmd);
+            expectResponse = cmd.expect_response();
+            if (!expectResponse) // SETPROP is "out of band"
+                cmd.set_function(oldCmd);
+            else
+                Receive(cmd);
+            break;
+        default:
+            ret = GenerateCall(dbg, cmd, msg, ret);
+            msg.set_expect_response(expectResponse);
+            if (!expectResponse) {
+                cmd.set_function(cmd.SKIP);
+                cmd.set_expect_response(expectResponse);
+            }
+            oldCmd = cmd.function();
+            Send(msg, cmd);
+            expectResponse = cmd.expect_response();
+            break;
+        }
+    }
+    return 0;
+}
+}; // namespace android {
diff --git a/opengl/libs/GLES2_dbg/src/vertex.cpp b/opengl/libs/GLES2_dbg/src/vertex.cpp
new file mode 100644
index 0000000..029ee3b
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/vertex.cpp
@@ -0,0 +1,211 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "header.h"
+
+namespace android
+{
+bool capture; // capture after each glDraw*
+}
+
+void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    DbgContext * const dbg = getDbgContextThreadSpecific();
+    glesv2debugger::Message msg, cmd;
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
+    bool expectResponse = dbg->expectResponse.Bit(glesv2debugger::Message_Function_glDrawArrays);
+    msg.set_expect_response(expectResponse);
+    msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
+    msg.set_arg0(mode);
+    msg.set_arg1(first);
+    msg.set_arg2(count);
+
+    msg.set_arg7(dbg->maxAttrib); // indicate capturing vertex data
+    if (dbg->hasNonVBOAttribs) {
+        std::string * const data = msg.mutable_data();
+        for (unsigned i = 0; i < count; i++)
+            dbg->Fetch(i + first, data);
+    }
+
+    void * pixels = NULL;
+    int viewport[4] = {};
+    cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    cmd.set_expect_response(expectResponse);
+    glesv2debugger::Message_Function oldCmd = cmd.function();
+    Send(msg, cmd);
+    expectResponse = cmd.expect_response();
+    while (true) {
+        msg.Clear();
+        nsecs_t c0 = systemTime(timeMode);
+        switch (cmd.function()) {
+        case glesv2debugger::Message_Function_CONTINUE:
+            dbg->hooks->gl.glDrawArrays(mode, first, count);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.set_context_id(reinterpret_cast<int>(dbg));
+            msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
+            msg.set_type(glesv2debugger::Message_Type_AfterCall);
+            msg.set_expect_response(expectResponse);
+            if (!expectResponse) {
+                cmd.set_function(glesv2debugger::Message_Function_SKIP);
+                cmd.set_expect_response(false);
+            }
+            oldCmd = cmd.function();
+            Send(msg, cmd);
+            expectResponse = cmd.expect_response();
+            // TODO: pack glReadPixels data with vertex data instead of
+            //  relying on sperate call for transport, this would allow
+            //  auto generated message loop using EXTEND_Debug macro
+            if (dbg->captureDraw > 0) {
+                dbg->captureDraw--;
+                dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
+//                LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
+//                     viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
+                pixels = dbg->GetReadPixelsBuffer(viewport[2] * viewport[3] *
+                                                  dbg->readBytesPerPixel);
+                Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
+                                   dbg->readFormat, dbg->readType, pixels);
+            }
+            break;
+        case glesv2debugger::Message_Function_SKIP:
+            return;
+        case glesv2debugger::Message_Function_SETPROP:
+            SetProp(dbg, cmd);
+            expectResponse = cmd.expect_response();
+            if (!expectResponse) // SETPROP is "out of band"
+                cmd.set_function(oldCmd);
+            else
+                Receive(cmd);
+            break;
+        default:
+            GenerateCall(dbg, cmd, msg, NULL);
+            msg.set_expect_response(expectResponse);
+            if (!expectResponse) {
+                cmd.set_function(cmd.SKIP);
+                cmd.set_expect_response(expectResponse);
+            }
+            oldCmd = cmd.function();
+            Send(msg, cmd);
+            expectResponse = cmd.expect_response();
+            break;
+        }
+    }
+}
+
+template<typename T>
+static inline void FetchIndexed(const unsigned count, const T * indices,
+                                std::string * const data, const DbgContext * const ctx)
+{
+    for (unsigned i = 0; i < count; i++) {
+        if (!ctx->indexBuffer)
+            data->append((const char *)(indices + i), sizeof(*indices));
+        if (ctx->hasNonVBOAttribs)
+            ctx->Fetch(indices[i], data);
+    }
+}
+
+void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+{
+    DbgContext * const dbg = getDbgContextThreadSpecific();
+    glesv2debugger::Message msg, cmd;
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
+    bool expectResponse = dbg->expectResponse.Bit(glesv2debugger::Message_Function_glDrawElements);
+    msg.set_expect_response(expectResponse);
+    msg.set_function(glesv2debugger::Message_Function_glDrawElements);
+    msg.set_arg0(mode);
+    msg.set_arg1(count);
+    msg.set_arg2(type);
+    msg.set_arg3(reinterpret_cast<int>(indices));
+
+    msg.set_arg7(dbg->maxAttrib); // indicate capturing vertex data
+    std::string * const data = msg.mutable_data();
+    if (GL_UNSIGNED_BYTE == type) {
+        if (dbg->indexBuffer)
+            FetchIndexed(count, (unsigned char *)dbg->indexBuffer->data +
+                         (unsigned long)indices, data, dbg);
+        else
+            FetchIndexed(count, (unsigned char *)indices, data, dbg);
+    } else if (GL_UNSIGNED_SHORT == type) {
+        if (dbg->indexBuffer)
+            FetchIndexed(count, (unsigned short *)((char *)dbg->indexBuffer->data +
+                                                   (unsigned long)indices), data, dbg);
+        else
+            FetchIndexed(count, (unsigned short *)indices, data, dbg);
+    } else
+        assert(0);
+
+    void * pixels = NULL;
+    int viewport[4] = {};
+    cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    cmd.set_expect_response(expectResponse);
+    glesv2debugger::Message_Function oldCmd = cmd.function();
+    Send(msg, cmd);
+    expectResponse = cmd.expect_response();
+    while (true) {
+        msg.Clear();
+        nsecs_t c0 = systemTime(timeMode);
+        switch (cmd.function()) {
+        case glesv2debugger::Message_Function_CONTINUE:
+            dbg->hooks->gl.glDrawElements(mode, count, type, indices);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.set_context_id(reinterpret_cast<int>(dbg));
+            msg.set_function(glesv2debugger::Message_Function_glDrawElements);
+            msg.set_type(glesv2debugger::Message_Type_AfterCall);
+            msg.set_expect_response(expectResponse);
+            if (!expectResponse) {
+                cmd.set_function(glesv2debugger::Message_Function_SKIP);
+                cmd.set_expect_response(false);
+            }
+            oldCmd = cmd.function();
+            Send(msg, cmd);
+            expectResponse = cmd.expect_response();
+            // TODO: pack glReadPixels data with vertex data instead of
+            //  relying on sperate call for transport, this would allow
+            //  auto generated message loop using EXTEND_Debug macro
+            if (dbg->captureDraw > 0) {
+                dbg->captureDraw--;
+                dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
+                pixels = dbg->GetReadPixelsBuffer(viewport[2] * viewport[3] *
+                                                  dbg->readBytesPerPixel);
+                Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
+                                   dbg->readFormat, dbg->readType, pixels);
+            }
+            break;
+        case glesv2debugger::Message_Function_SKIP:
+            return;
+        case glesv2debugger::Message_Function_SETPROP:
+            SetProp(dbg, cmd);
+            expectResponse = cmd.expect_response();
+            if (!expectResponse) // SETPROP is "out of band"
+                cmd.set_function(oldCmd);
+            else
+                Receive(cmd);
+            break;
+        default:
+            GenerateCall(dbg, cmd, msg, NULL);
+            msg.set_expect_response(expectResponse);
+            if (!expectResponse) {
+                cmd.set_function(cmd.SKIP);
+                cmd.set_expect_response(expectResponse);
+            }
+            oldCmd = cmd.function();
+            Send(msg, cmd);
+            expectResponse = cmd.expect_response();
+            break;
+        }
+    }
+}
diff --git a/opengl/libs/GLES2_dbg/test/Android.mk b/opengl/libs/GLES2_dbg/test/Android.mk
new file mode 100644
index 0000000..14a84b4
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/test/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH) \
+    $(LOCAL_PATH)/../src \
+    $(LOCAL_PATH)/../../ \
+    external/gtest/include \
+    external/stlport/stlport \
+    external/protobuf/src \
+    bionic \
+    external \
+#
+
+LOCAL_SRC_FILES:= \
+    test_main.cpp \
+    test_server.cpp \
+    test_socket.cpp \
+#
+
+LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2_dbg libstlport
+LOCAL_STATIC_LIBRARIES := libgtest libprotobuf-cpp-2.3.0-lite liblzf
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE:= libGLESv2_dbg_test
+
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+ifneq ($(TARGET_SIMULATOR),true)
+    LOCAL_C_INCLUDES += bionic/libc/private
+endif
+
+LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS += -fvisibility=hidden
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/opengl/libs/GLES2_dbg/test/test_main.cpp b/opengl/libs/GLES2_dbg/test/test_main.cpp
new file mode 100644
index 0000000..058bea4
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/test/test_main.cpp
@@ -0,0 +1,234 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "header.h"
+#include "gtest/gtest.h"
+#include "hooks.h"
+
+namespace
+{
+
+// The fixture for testing class Foo.
+class DbgContextTest : public ::testing::Test
+{
+protected:
+    android::DbgContext dbg;
+    gl_hooks_t hooks;
+
+    DbgContextTest()
+            : dbg(1, &hooks, 32, GL_RGBA, GL_UNSIGNED_BYTE) {
+        // You can do set-up work for each test here.
+        hooks.gl.glGetError = GetError;
+    }
+
+    static GLenum GetError() {
+        return GL_NO_ERROR;
+    }
+
+    virtual ~DbgContextTest() {
+        // You can do clean-up work that doesn't throw exceptions here.
+    }
+
+    // If the constructor and destructor are not enough for setting up
+    // and cleaning up each test, you can define the following methods:
+
+    virtual void SetUp() {
+        // Code here will be called immediately after the constructor (right
+        // before each test).
+    }
+
+    virtual void TearDown() {
+        // Code here will be called immediately after each test (right
+        // before the destructor).
+    }
+};
+
+TEST_F(DbgContextTest, GetReadPixelBuffer)
+{
+    const unsigned int bufferSize = 512;
+    // test that it's allocating two buffers and swapping them
+    void * const buffer0 = dbg.GetReadPixelsBuffer(bufferSize);
+    ASSERT_NE((void *)NULL, buffer0);
+    for (unsigned int i = 0; i < bufferSize / sizeof(unsigned int); i++) {
+        EXPECT_EQ(0, ((unsigned int *)buffer0)[i])
+        << "GetReadPixelsBuffer should allocate and zero";
+        ((unsigned int *)buffer0)[i] = i * 13;
+    }
+
+    void * const buffer1 = dbg.GetReadPixelsBuffer(bufferSize);
+    ASSERT_NE((void *)NULL, buffer1);
+    EXPECT_NE(buffer0, buffer1);
+    for (unsigned int i = 0; i < bufferSize / sizeof(unsigned int); i++) {
+        EXPECT_EQ(0, ((unsigned int *)buffer1)[i])
+        << "GetReadPixelsBuffer should allocate and zero";
+        ((unsigned int *)buffer1)[i] = i * 17;
+    }
+
+    void * const buffer2 = dbg.GetReadPixelsBuffer(bufferSize);
+    EXPECT_EQ(buffer2, buffer0);
+    for (unsigned int i = 0; i < bufferSize / sizeof(unsigned int); i++)
+        EXPECT_EQ(i * 13, ((unsigned int *)buffer2)[i])
+        << "GetReadPixelsBuffer should swap buffers";
+
+    void * const buffer3 = dbg.GetReadPixelsBuffer(bufferSize);
+    EXPECT_EQ(buffer3, buffer1);
+    for (unsigned int i = 0; i < bufferSize / sizeof(unsigned int); i++)
+        EXPECT_EQ(i * 17, ((unsigned int *)buffer3)[i])
+        << "GetReadPixelsBuffer should swap buffers";
+
+    void * const buffer4 = dbg.GetReadPixelsBuffer(bufferSize);
+    EXPECT_NE(buffer3, buffer4);
+    EXPECT_EQ(buffer0, buffer2);
+    EXPECT_EQ(buffer1, buffer3);
+    EXPECT_EQ(buffer2, buffer4);
+
+    // it reallocs as necessary; 0 size may result in NULL
+    for (unsigned int i = 0; i < 42; i++) {
+        void * const buffer = dbg.GetReadPixelsBuffer(((i & 7)) << 20);
+        EXPECT_NE((void *)NULL, buffer)
+        << "should be able to get a variety of reasonable sizes";
+        EXPECT_TRUE(dbg.IsReadPixelBuffer(buffer));
+    }
+}
+
+TEST_F(DbgContextTest, CompressReadPixelBuffer)
+{
+    const unsigned int bufferSize = dbg.LZF_CHUNK_SIZE * 4 + 33;
+    std::string out;
+    unsigned char * buffer = (unsigned char *)dbg.GetReadPixelsBuffer(bufferSize);
+    for (unsigned int i = 0; i < bufferSize; i++)
+        buffer[i] = i * 13;
+    dbg.CompressReadPixelBuffer(&out);
+    uint32_t decompSize = 0;
+    ASSERT_LT(12, out.length()); // at least written chunk header
+    ASSERT_EQ(bufferSize, *(uint32_t *)out.data())
+    << "total decompressed size should be as requested in GetReadPixelsBuffer";
+    for (unsigned int i = 4; i < out.length();) {
+        const uint32_t outSize = *(uint32_t *)(out.data() + i);
+        i += 4;
+        const uint32_t inSize = *(uint32_t *)(out.data() + i);
+        i += 4;
+        if (inSize == 0)
+            i += outSize; // chunk not compressed
+        else
+            i += inSize; // skip the actual compressed chunk
+        decompSize += outSize;
+    }
+    ASSERT_EQ(bufferSize, decompSize);
+    decompSize = 0;
+
+    unsigned char * decomp = dbg.Decompress(out.data(), out.length(), &decompSize);
+    ASSERT_EQ(decompSize, bufferSize);
+    for (unsigned int i = 0; i < bufferSize; i++)
+        EXPECT_EQ((unsigned char)(i * 13), decomp[i]) << "xor with 0 ref is identity";
+    free(decomp);
+
+    buffer = (unsigned char *)dbg.GetReadPixelsBuffer(bufferSize);
+    for (unsigned int i = 0; i < bufferSize; i++)
+        buffer[i] = i * 13;
+    out.clear();
+    dbg.CompressReadPixelBuffer(&out);
+    decompSize = 0;
+    decomp = dbg.Decompress(out.data(), out.length(), &decompSize);
+    ASSERT_EQ(decompSize, bufferSize);
+    for (unsigned int i = 0; i < bufferSize; i++)
+        EXPECT_EQ(0, decomp[i]) << "xor with same ref is 0";
+    free(decomp);
+
+    buffer = (unsigned char *)dbg.GetReadPixelsBuffer(bufferSize);
+    for (unsigned int i = 0; i < bufferSize; i++)
+        buffer[i] = i * 19;
+    out.clear();
+    dbg.CompressReadPixelBuffer(&out);
+    decompSize = 0;
+    decomp = dbg.Decompress(out.data(), out.length(), &decompSize);
+    ASSERT_EQ(decompSize, bufferSize);
+    for (unsigned int i = 0; i < bufferSize; i++)
+        EXPECT_EQ((unsigned char)(i * 13) ^ (unsigned char)(i * 19), decomp[i])
+        << "xor ref";
+    free(decomp);
+}
+
+TEST_F(DbgContextTest, UseProgram)
+{
+    static const GLuint _program = 74568;
+    static const struct Attribute {
+        const char * name;
+        GLint location;
+        GLint size;
+        GLenum type;
+    } _attributes [] = {
+        {"aaa", 2, 2, GL_FLOAT_VEC2},
+        {"bb", 6, 2, GL_FLOAT_MAT2},
+        {"c", 1, 1, GL_FLOAT},
+    };
+    static const unsigned int _attributeCount = sizeof(_attributes) / sizeof(*_attributes);
+    struct GL {
+        static void GetProgramiv(GLuint program, GLenum pname, GLint* params) {
+            EXPECT_EQ(_program, program);
+            ASSERT_NE((GLint *)NULL, params);
+            switch (pname) {
+            case GL_ACTIVE_ATTRIBUTES:
+                *params = _attributeCount;
+                return;
+            case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+                *params = 4; // includes NULL terminator
+                return;
+            default:
+                ADD_FAILURE() << "not handled pname: " << pname;
+            }
+        }
+
+        static GLint GetAttribLocation(GLuint program, const GLchar* name) {
+            EXPECT_EQ(_program, program);
+            for (unsigned int i = 0; i < _attributeCount; i++)
+                if (!strcmp(name, _attributes[i].name))
+                    return _attributes[i].location;
+            ADD_FAILURE() << "unknown attribute name: " << name;
+            return -1;
+        }
+
+        static void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
+                                    GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
+            EXPECT_EQ(_program, program);
+            ASSERT_LT(index, _attributeCount);
+            const Attribute & att = _attributes[index];
+            ASSERT_GE(bufsize, strlen(att.name) + 1);
+            ASSERT_NE((GLint *)NULL, size);
+            ASSERT_NE((GLenum *)NULL, type);
+            ASSERT_NE((GLchar *)NULL, name);
+            strcpy(name, att.name);
+            if (length)
+                *length = strlen(name) + 1;
+            *size = att.size;
+            *type = att.type;
+        }
+    };
+    hooks.gl.glGetProgramiv = GL::GetProgramiv;
+    hooks.gl.glGetAttribLocation = GL::GetAttribLocation;
+    hooks.gl.glGetActiveAttrib = GL::GetActiveAttrib;
+    dbg.glUseProgram(_program);
+    EXPECT_EQ(10, dbg.maxAttrib);
+    dbg.glUseProgram(0);
+    EXPECT_EQ(0, dbg.maxAttrib);
+}
+}  // namespace
+
+int main(int argc, char **argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/opengl/libs/GLES2_dbg/test/test_server.cpp b/opengl/libs/GLES2_dbg/test/test_server.cpp
new file mode 100644
index 0000000..bbbe913
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/test/test_server.cpp
@@ -0,0 +1,245 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "header.h"
+#include "gtest/gtest.h"
+#include "hooks.h"
+
+namespace android
+{
+extern FILE * file;
+extern unsigned int MAX_FILE_SIZE;
+};
+
+// tmpfile fails, so need to manually make a writable file first
+static const char * filePath = "/data/local/tmp/dump.gles2dbg";
+
+class ServerFileTest : public ::testing::Test
+{
+protected:
+    ServerFileTest() { }
+
+    virtual ~ServerFileTest() { }
+
+    virtual void SetUp() {
+        MAX_FILE_SIZE = 8 << 20;
+        ASSERT_EQ((FILE *)NULL, file);
+        file = fopen("/data/local/tmp/dump.gles2dbg", "wb+");
+        ASSERT_NE((FILE *)NULL, file) << "make sure file is writable: "
+        << filePath;
+    }
+
+    virtual void TearDown() {
+        ASSERT_NE((FILE *)NULL, file);
+        fclose(file);
+        file = NULL;
+    }
+
+    void Read(glesv2debugger::Message & msg) const {
+        msg.Clear();
+        uint32_t len = 0;
+        ASSERT_EQ(sizeof(len), fread(&len, 1, sizeof(len), file));
+        ASSERT_GT(len, 0u);
+        char * buffer = new char [len];
+        ASSERT_EQ(len, fread(buffer, 1, len, file));
+        msg.ParseFromArray(buffer, len);
+        delete buffer;
+    }
+
+    void CheckNoAvailable() {
+        const long pos = ftell(file);
+        fseek(file, 0, SEEK_END);
+        EXPECT_EQ(pos, ftell(file)) << "check no available";
+    }
+};
+
+TEST_F(ServerFileTest, Send)
+{
+    glesv2debugger::Message msg, cmd, read;
+    msg.set_context_id(1);
+    msg.set_function(msg.glFinish);
+    msg.set_expect_response(false);
+    msg.set_type(msg.BeforeCall);
+    rewind(file);
+    android::Send(msg, cmd);
+    rewind(file);
+    Read(read);
+    EXPECT_EQ(msg.context_id(), read.context_id());
+    EXPECT_EQ(msg.function(), read.function());
+    EXPECT_EQ(msg.expect_response(), read.expect_response());
+    EXPECT_EQ(msg.type(), read.type());
+}
+
+TEST_F(ServerFileTest, CreateDbgContext)
+{
+    gl_hooks_t hooks;
+    struct Constant {
+        GLenum pname;
+        GLint param;
+    };
+    static const Constant constants [] = {
+        {GL_MAX_VERTEX_ATTRIBS, 16},
+        {GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 32},
+        {GL_IMPLEMENTATION_COLOR_READ_FORMAT, GL_RGBA},
+        {GL_IMPLEMENTATION_COLOR_READ_TYPE, GL_UNSIGNED_BYTE},
+    };
+    struct HookMock {
+        static void GetIntegerv(GLenum pname, GLint* params) {
+            ASSERT_TRUE(params != NULL);
+            for (unsigned int i = 0; i < sizeof(constants) / sizeof(*constants); i++)
+                if (pname == constants[i].pname) {
+                    *params = constants[i].param;
+                    return;
+                }
+            FAIL() << "GetIntegerv unknown pname: " << pname;
+        }
+        static GLenum GetError() {
+            return GL_NO_ERROR;
+        }
+    };
+    hooks.gl.glGetError = HookMock::GetError;
+    hooks.gl.glGetIntegerv = HookMock::GetIntegerv;
+    DbgContext * const dbg = CreateDbgContext(1, &hooks);
+    ASSERT_TRUE(dbg != NULL);
+    EXPECT_TRUE(dbg->vertexAttribs != NULL);
+
+    rewind(file);
+    glesv2debugger::Message read;
+    for (unsigned int i = 0; i < 2; i++) {
+        Read(read);
+        EXPECT_EQ(reinterpret_cast<int>(dbg), read.context_id());
+        EXPECT_FALSE(read.expect_response());
+        EXPECT_EQ(read.Response, read.type());
+        EXPECT_EQ(read.SETPROP, read.function());
+        EXPECT_EQ(read.GLConstant, read.prop());
+        GLint expectedConstant = 0;
+        HookMock::GetIntegerv(read.arg0(), &expectedConstant);
+        EXPECT_EQ(expectedConstant, read.arg1());
+    }
+    CheckNoAvailable();
+    dbgReleaseThread();
+}
+
+void * glNoop()
+{
+    return 0;
+}
+
+class ServerFileContextTest : public ServerFileTest
+{
+protected:
+    DbgContext* dbg;
+    gl_hooks_t hooks;
+
+    ServerFileContextTest() { }
+
+    virtual ~ServerFileContextTest() { }
+
+    virtual void SetUp() {
+        ServerFileTest::SetUp();
+
+        dbg = new DbgContext(1, &hooks, 32, GL_RGBA, GL_UNSIGNED_BYTE);
+        ASSERT_NE((void *)NULL, dbg);
+        for (unsigned int i = 0; i < sizeof(hooks) / sizeof(void *); i++)
+            ((void **)&hooks)[i] = reinterpret_cast<void *>(glNoop);
+    }
+
+    virtual void TearDown() {
+        ServerFileTest::TearDown();
+    }
+};
+
+TEST_F(ServerFileContextTest, MessageLoop)
+{
+    static const int arg0 = 45;
+    static const float arg7 = -87.2331f;
+    static const int arg8 = -3;
+    static const int * ret = reinterpret_cast<int *>(870);
+
+    struct Caller : public FunctionCall {
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            msg.set_arg0(arg0);
+            msg.set_arg7((int &)arg7);
+            msg.set_arg8(arg8);
+            return ret;
+        }
+    } caller;
+    const int contextId = reinterpret_cast<int>(dbg);
+    glesv2debugger::Message msg, read;
+
+    EXPECT_EQ(ret, MessageLoop(caller, msg, msg.glFinish));
+
+    rewind(file);
+    Read(read);
+    EXPECT_EQ(contextId, read.context_id());
+    EXPECT_EQ(read.glFinish, read.function());
+    EXPECT_EQ(false, read.expect_response());
+    EXPECT_EQ(read.BeforeCall, read.type());
+
+    Read(read);
+    EXPECT_EQ(contextId, read.context_id());
+    EXPECT_EQ(read.glFinish, read.function());
+    EXPECT_EQ(false, read.expect_response());
+    EXPECT_EQ(read.AfterCall, read.type());
+    EXPECT_TRUE(read.has_time());
+    EXPECT_EQ(arg0, read.arg0());
+    const int readArg7 = read.arg7();
+    EXPECT_EQ(arg7, (float &)readArg7);
+    EXPECT_EQ(arg8, read.arg8());
+
+    const long pos = ftell(file);
+    fseek(file, 0, SEEK_END);
+    EXPECT_EQ(pos, ftell(file))
+    << "should only write the BeforeCall and AfterCall messages";
+}
+
+TEST_F(ServerFileContextTest, DisableEnableVertexAttribArray)
+{
+    Debug_glEnableVertexAttribArray(dbg->MAX_VERTEX_ATTRIBS + 2); // should just ignore invalid index
+
+    glesv2debugger::Message read;
+    rewind(file);
+    Read(read);
+    EXPECT_EQ(read.glEnableVertexAttribArray, read.function());
+    EXPECT_EQ(dbg->MAX_VERTEX_ATTRIBS + 2, read.arg0());
+    Read(read);
+
+    rewind(file);
+    Debug_glDisableVertexAttribArray(dbg->MAX_VERTEX_ATTRIBS + 4); // should just ignore invalid index
+    rewind(file);
+    Read(read);
+    Read(read);
+
+    for (unsigned int i = 0; i < dbg->MAX_VERTEX_ATTRIBS; i += 5) {
+        rewind(file);
+        Debug_glEnableVertexAttribArray(i);
+        EXPECT_TRUE(dbg->vertexAttribs[i].enabled);
+        rewind(file);
+        Read(read);
+        EXPECT_EQ(read.glEnableVertexAttribArray, read.function());
+        EXPECT_EQ(i, read.arg0());
+        Read(read);
+
+        rewind(file);
+        Debug_glDisableVertexAttribArray(i);
+        EXPECT_FALSE(dbg->vertexAttribs[i].enabled);
+        rewind(file);
+        Read(read);
+        EXPECT_EQ(read.glDisableVertexAttribArray, read.function());
+        EXPECT_EQ(i, read.arg0());
+        Read(read);
+    }
+}
diff --git a/opengl/libs/GLES2_dbg/test/test_socket.cpp b/opengl/libs/GLES2_dbg/test/test_socket.cpp
new file mode 100644
index 0000000..b2148ac
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/test/test_socket.cpp
@@ -0,0 +1,468 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include "header.h"
+#include "gtest/gtest.h"
+#include "hooks.h"
+
+namespace android
+{
+extern int serverSock, clientSock;
+};
+
+void * glNoop();
+
+class SocketContextTest : public ::testing::Test
+{
+protected:
+    DbgContext* dbg;
+    gl_hooks_t hooks;
+    int sock;
+    char * buffer;
+    unsigned int bufferSize;
+
+    SocketContextTest() : sock(-1) {
+    }
+
+    virtual ~SocketContextTest() {
+    }
+
+    virtual void SetUp() {
+        dbg = new DbgContext(1, &hooks, 32, GL_RGBA, GL_UNSIGNED_BYTE);
+        ASSERT_TRUE(dbg != NULL);
+        for (unsigned int i = 0; i < sizeof(hooks) / sizeof(void *); i++)
+            ((void **)&hooks)[i] = (void *)glNoop;
+
+        int socks[2] = {-1, -1};
+        ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, socks));
+        clientSock = socks[0];
+        sock = socks[1];
+
+        bufferSize = 128;
+        buffer = new char [128];
+        ASSERT_NE((char *)NULL, buffer);
+    }
+
+    virtual void TearDown() {
+        close(sock);
+        close(clientSock);
+        clientSock = -1;
+        delete buffer;
+    }
+
+    void Write(glesv2debugger::Message & msg) const {
+        msg.set_context_id((int)dbg);
+        msg.set_type(msg.Response);
+        ASSERT_TRUE(msg.has_context_id());
+        ASSERT_TRUE(msg.has_function());
+        ASSERT_TRUE(msg.has_type());
+        ASSERT_TRUE(msg.has_expect_response());
+        static std::string str;
+        msg.SerializeToString(&str);
+        const uint32_t len = str.length();
+        ASSERT_EQ(sizeof(len), send(sock, &len, sizeof(len), 0));
+        ASSERT_EQ(str.length(), send(sock, str.data(), str.length(), 0));
+    }
+
+    void Read(glesv2debugger::Message & msg) {
+        int available = 0;
+        ASSERT_EQ(0, ioctl(sock, FIONREAD, &available));
+        ASSERT_GT(available, 0);
+        uint32_t len = 0;
+        ASSERT_EQ(sizeof(len), recv(sock, &len, sizeof(len), 0));
+        if (len > bufferSize) {
+            bufferSize = len;
+            buffer = new char[bufferSize];
+            ASSERT_TRUE(buffer != NULL);
+        }
+        ASSERT_EQ(len, recv(sock, buffer, len, 0));
+        msg.Clear();
+        msg.ParseFromArray(buffer, len);
+        ASSERT_TRUE(msg.has_context_id());
+        ASSERT_TRUE(msg.has_function());
+        ASSERT_TRUE(msg.has_type());
+        ASSERT_TRUE(msg.has_expect_response());
+    }
+
+    void CheckNoAvailable() {
+        int available = 0;
+        ASSERT_EQ(0, ioctl(sock, FIONREAD, &available));
+        ASSERT_EQ(available, 0);
+    }
+};
+
+TEST_F(SocketContextTest, MessageLoopSkip)
+{
+    static const int arg0 = 45;
+    static const float arg7 = -87.2331f;
+    static const int arg8 = -3;
+    static const int * ret = (int *)870;
+
+    struct Caller : public FunctionCall {
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            msg.set_arg0(arg0);
+            msg.set_arg7((int &)arg7);
+            msg.set_arg8(arg8);
+            return ret;
+        }
+    } caller;
+    glesv2debugger::Message msg, read, cmd;
+    dbg->expectResponse.Bit(msg.glFinish, true);
+
+    cmd.set_function(cmd.SKIP);
+    cmd.set_expect_response(false);
+    Write(cmd);
+
+    EXPECT_NE(ret, MessageLoop(caller, msg, msg.glFinish));
+
+    Read(read);
+    EXPECT_EQ(read.glFinish, read.function());
+    EXPECT_EQ(read.BeforeCall, read.type());
+    EXPECT_NE(arg0, read.arg0());
+    EXPECT_NE((int &)arg7, read.arg7());
+    EXPECT_NE(arg8, read.arg8());
+
+    CheckNoAvailable();
+}
+
+TEST_F(SocketContextTest, MessageLoopContinue)
+{
+    static const int arg0 = GL_FRAGMENT_SHADER;
+    static const int ret = -342;
+    struct Caller : public FunctionCall {
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            msg.set_ret(ret);
+            return (int *)ret;
+        }
+    } caller;
+    glesv2debugger::Message msg, read, cmd;
+    dbg->expectResponse.Bit(msg.glCreateShader, true);
+
+    cmd.set_function(cmd.CONTINUE);
+    cmd.set_expect_response(false); // MessageLoop should automatically skip after continue
+    Write(cmd);
+
+    msg.set_arg0(arg0);
+    EXPECT_EQ((int *)ret, MessageLoop(caller, msg, msg.glCreateShader));
+
+    Read(read);
+    EXPECT_EQ(read.glCreateShader, read.function());
+    EXPECT_EQ(read.BeforeCall, read.type());
+    EXPECT_EQ(arg0, read.arg0());
+
+    Read(read);
+    EXPECT_EQ(read.glCreateShader, read.function());
+    EXPECT_EQ(read.AfterCall, read.type());
+    EXPECT_EQ(ret, read.ret());
+
+    CheckNoAvailable();
+}
+
+TEST_F(SocketContextTest, MessageLoopGenerateCall)
+{
+    static const int ret = -342;
+    static unsigned int createShader, createProgram;
+    createShader = 0;
+    createProgram = 0;
+    struct Caller : public FunctionCall {
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int r = (int)_c->glCreateProgram();
+            msg.set_ret(r);
+            return (int *)r;
+        }
+        static GLuint CreateShader(const GLenum type) {
+            createShader++;
+            return type;
+        }
+        static GLuint CreateProgram() {
+            createProgram++;
+            return ret;
+        }
+    } caller;
+    glesv2debugger::Message msg, read, cmd;
+    hooks.gl.glCreateShader = caller.CreateShader;
+    hooks.gl.glCreateProgram = caller.CreateProgram;
+    dbg->expectResponse.Bit(msg.glCreateProgram, true);
+
+    cmd.set_function(cmd.glCreateShader);
+    cmd.set_arg0(GL_FRAGMENT_SHADER);
+    cmd.set_expect_response(true);
+    Write(cmd);
+
+    cmd.Clear();
+    cmd.set_function(cmd.CONTINUE);
+    cmd.set_expect_response(true);
+    Write(cmd);
+
+    cmd.set_function(cmd.glCreateShader);
+    cmd.set_arg0(GL_VERTEX_SHADER);
+    cmd.set_expect_response(false); // MessageLoop should automatically skip afterwards
+    Write(cmd);
+
+    EXPECT_EQ((int *)ret, MessageLoop(caller, msg, msg.glCreateProgram));
+
+    Read(read);
+    EXPECT_EQ(read.glCreateProgram, read.function());
+    EXPECT_EQ(read.BeforeCall, read.type());
+
+    Read(read);
+    EXPECT_EQ(read.glCreateShader, read.function());
+    EXPECT_EQ(read.AfterGeneratedCall, read.type());
+    EXPECT_EQ(GL_FRAGMENT_SHADER, read.ret());
+
+    Read(read);
+    EXPECT_EQ(read.glCreateProgram, read.function());
+    EXPECT_EQ(read.AfterCall, read.type());
+    EXPECT_EQ(ret, read.ret());
+
+    Read(read);
+    EXPECT_EQ(read.glCreateShader, read.function());
+    EXPECT_EQ(read.AfterGeneratedCall, read.type());
+    EXPECT_EQ(GL_VERTEX_SHADER, read.ret());
+
+    EXPECT_EQ(2, createShader);
+    EXPECT_EQ(1, createProgram);
+
+    CheckNoAvailable();
+}
+
+TEST_F(SocketContextTest, MessageLoopSetProp)
+{
+    static const int ret = -342;
+    static unsigned int createShader, createProgram;
+    createShader = 0;
+    createProgram = 0;
+    struct Caller : public FunctionCall {
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int r = (int)_c->glCreateProgram();
+            msg.set_ret(r);
+            return (int *)r;
+        }
+        static GLuint CreateShader(const GLenum type) {
+            createShader++;
+            return type;
+        }
+        static GLuint CreateProgram() {
+            createProgram++;
+            return ret;
+        }
+    } caller;
+    glesv2debugger::Message msg, read, cmd;
+    hooks.gl.glCreateShader = caller.CreateShader;
+    hooks.gl.glCreateProgram = caller.CreateProgram;
+    dbg->expectResponse.Bit(msg.glCreateProgram, false);
+
+    cmd.set_function(cmd.SETPROP);
+    cmd.set_prop(cmd.ExpectResponse);
+    cmd.set_arg0(cmd.glCreateProgram);
+    cmd.set_arg1(true);
+    cmd.set_expect_response(true);
+    Write(cmd);
+
+    cmd.Clear();
+    cmd.set_function(cmd.glCreateShader);
+    cmd.set_arg0(GL_FRAGMENT_SHADER);
+    cmd.set_expect_response(true);
+    Write(cmd);
+
+    cmd.set_function(cmd.SETPROP);
+    cmd.set_prop(cmd.CaptureDraw);
+    cmd.set_arg0(819);
+    cmd.set_expect_response(true);
+    Write(cmd);
+
+    cmd.Clear();
+    cmd.set_function(cmd.CONTINUE);
+    cmd.set_expect_response(true);
+    Write(cmd);
+
+    cmd.set_function(cmd.glCreateShader);
+    cmd.set_arg0(GL_VERTEX_SHADER);
+    cmd.set_expect_response(false); // MessageLoop should automatically skip afterwards
+    Write(cmd);
+
+    EXPECT_EQ((int *)ret, MessageLoop(caller, msg, msg.glCreateProgram));
+
+    EXPECT_TRUE(dbg->expectResponse.Bit(msg.glCreateProgram));
+    EXPECT_EQ(819, dbg->captureDraw);
+
+    Read(read);
+    EXPECT_EQ(read.glCreateProgram, read.function());
+    EXPECT_EQ(read.BeforeCall, read.type());
+
+    Read(read);
+    EXPECT_EQ(read.glCreateShader, read.function());
+    EXPECT_EQ(read.AfterGeneratedCall, read.type());
+    EXPECT_EQ(GL_FRAGMENT_SHADER, read.ret());
+
+    Read(read);
+    EXPECT_EQ(read.glCreateProgram, read.function());
+    EXPECT_EQ(read.AfterCall, read.type());
+    EXPECT_EQ(ret, read.ret());
+
+    Read(read);
+    EXPECT_EQ(read.glCreateShader, read.function());
+    EXPECT_EQ(read.AfterGeneratedCall, read.type());
+    EXPECT_EQ(GL_VERTEX_SHADER, read.ret());
+
+    EXPECT_EQ(2, createShader);
+    EXPECT_EQ(1, createProgram);
+
+    CheckNoAvailable();
+}
+
+TEST_F(SocketContextTest, TexImage2D)
+{
+    static const GLenum _target = GL_TEXTURE_2D;
+    static const GLint _level = 1, _internalformat = GL_RGBA;
+    static const GLsizei _width = 2, _height = 2;
+    static const GLint _border = 333;
+    static const GLenum _format = GL_RGB, _type = GL_UNSIGNED_SHORT_5_6_5;
+    static const short _pixels [_width * _height] = {11, 22, 33, 44};
+    static unsigned int texImage2D;
+    texImage2D = 0;
+
+    struct Caller {
+        static void TexImage2D(GLenum target, GLint level, GLint internalformat,
+                               GLsizei width, GLsizei height, GLint border,
+                               GLenum format, GLenum type, const GLvoid* pixels) {
+            EXPECT_EQ(_target, target);
+            EXPECT_EQ(_level, level);
+            EXPECT_EQ(_internalformat, internalformat);
+            EXPECT_EQ(_width, width);
+            EXPECT_EQ(_height, height);
+            EXPECT_EQ(_border, border);
+            EXPECT_EQ(_format, format);
+            EXPECT_EQ(_type, type);
+            EXPECT_EQ(0, memcmp(_pixels, pixels, sizeof(_pixels)));
+            texImage2D++;
+        }
+    } caller;
+    glesv2debugger::Message msg, read, cmd;
+    hooks.gl.glTexImage2D = caller.TexImage2D;
+    dbg->expectResponse.Bit(msg.glTexImage2D, false);
+
+    Debug_glTexImage2D(_target, _level, _internalformat, _width, _height, _border,
+                       _format, _type, _pixels);
+    EXPECT_EQ(1, texImage2D);
+
+    Read(read);
+    EXPECT_EQ(read.glTexImage2D, read.function());
+    EXPECT_EQ(read.BeforeCall, read.type());
+    EXPECT_EQ(_target, read.arg0());
+    EXPECT_EQ(_level, read.arg1());
+    EXPECT_EQ(_internalformat, read.arg2());
+    EXPECT_EQ(_width, read.arg3());
+    EXPECT_EQ(_height, read.arg4());
+    EXPECT_EQ(_border, read.arg5());
+    EXPECT_EQ(_format, read.arg6());
+    EXPECT_EQ(_type, read.arg7());
+
+    EXPECT_TRUE(read.has_data());
+    uint32_t dataLen = 0;
+    const unsigned char * data = dbg->Decompress(read.data().data(),
+                                 read.data().length(), &dataLen);
+    EXPECT_EQ(sizeof(_pixels), dataLen);
+    if (sizeof(_pixels) == dataLen)
+        EXPECT_EQ(0, memcmp(_pixels, data, sizeof(_pixels)));
+
+    Read(read);
+    EXPECT_EQ(read.glTexImage2D, read.function());
+    EXPECT_EQ(read.AfterCall, read.type());
+
+    CheckNoAvailable();
+}
+
+TEST_F(SocketContextTest, CopyTexImage2D)
+{
+    static const GLenum _target = GL_TEXTURE_2D;
+    static const GLint _level = 1, _internalformat = GL_RGBA;
+    static const GLint _x = 9, _y = 99;
+    static const GLsizei _width = 2, _height = 3;
+    static const GLint _border = 333;
+    static const int _pixels [_width * _height] = {11, 22, 33, 44, 55, 66};
+    static unsigned int copyTexImage2D, readPixels;
+    copyTexImage2D = 0, readPixels = 0;
+
+    struct Caller {
+        static void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
+                                   GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
+            EXPECT_EQ(_target, target);
+            EXPECT_EQ(_level, level);
+            EXPECT_EQ(_internalformat, internalformat);
+            EXPECT_EQ(_x, x);
+            EXPECT_EQ(_y, y);
+            EXPECT_EQ(_width, width);
+            EXPECT_EQ(_height, height);
+            EXPECT_EQ(_border, border);
+            copyTexImage2D++;
+        }
+        static void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+                               GLenum format, GLenum type, GLvoid* pixels) {
+            EXPECT_EQ(_x, x);
+            EXPECT_EQ(_y, y);
+            EXPECT_EQ(_width, width);
+            EXPECT_EQ(_height, height);
+            EXPECT_EQ(GL_RGBA, format);
+            EXPECT_EQ(GL_UNSIGNED_BYTE, type);
+            ASSERT_TRUE(pixels != NULL);
+            memcpy(pixels, _pixels, sizeof(_pixels));
+            readPixels++;
+        }
+    } caller;
+    glesv2debugger::Message msg, read, cmd;
+    hooks.gl.glCopyTexImage2D = caller.CopyTexImage2D;
+    hooks.gl.glReadPixels = caller.ReadPixels;
+    dbg->expectResponse.Bit(msg.glCopyTexImage2D, false);
+
+    Debug_glCopyTexImage2D(_target, _level, _internalformat, _x, _y, _width, _height,
+                           _border);
+    ASSERT_EQ(1, copyTexImage2D);
+    ASSERT_EQ(1, readPixels);
+
+    Read(read);
+    EXPECT_EQ(read.glCopyTexImage2D, read.function());
+    EXPECT_EQ(read.BeforeCall, read.type());
+    EXPECT_EQ(_target, read.arg0());
+    EXPECT_EQ(_level, read.arg1());
+    EXPECT_EQ(_internalformat, read.arg2());
+    EXPECT_EQ(_x, read.arg3());
+    EXPECT_EQ(_y, read.arg4());
+    EXPECT_EQ(_width, read.arg5());
+    EXPECT_EQ(_height, read.arg6());
+    EXPECT_EQ(_border, read.arg7());
+
+    EXPECT_TRUE(read.has_data());
+    EXPECT_EQ(read.ReferencedImage, read.data_type());
+    EXPECT_EQ(GL_RGBA, read.pixel_format());
+    EXPECT_EQ(GL_UNSIGNED_BYTE, read.pixel_type());
+    uint32_t dataLen = 0;
+    unsigned char * const data = dbg->Decompress(read.data().data(),
+                                 read.data().length(), &dataLen);
+    ASSERT_EQ(sizeof(_pixels), dataLen);
+    for (unsigned i = 0; i < sizeof(_pixels) / sizeof(*_pixels); i++)
+        EXPECT_EQ(_pixels[i], ((const int *)data)[i]) << "xor with 0 ref is identity";
+    free(data);
+
+    Read(read);
+    EXPECT_EQ(read.glCopyTexImage2D, read.function());
+    EXPECT_EQ(read.AfterCall, read.type());
+
+    CheckNoAvailable();
+}
diff --git a/opengl/libs/debug.in b/opengl/libs/debug.in
new file mode 100644
index 0000000..882b2da
--- /dev/null
+++ b/opengl/libs/debug.in
@@ -0,0 +1,235 @@
+// the following functions are not defined in GLESv2_dbg
+TRACE_GL_VOID(glAlphaFunc, (GLenum func, GLclampf ref), (func, ref), 2, "GLenum", func, "GLclampf", ref)
+TRACE_GL_VOID(glAlphaFuncx, (GLenum func, GLclampx ref), (func, ref), 2, "GLenum", func, "GLclampx", ref)
+TRACE_GL_VOID(glAlphaFuncxOES, (GLenum func, GLclampx ref), (func, ref), 2, "GLenum", func, "GLclampx", ref)
+TRACE_GL_VOID(glBeginPerfMonitorAMD, (GLuint monitor), (monitor), 1, "GLuint", monitor)
+TRACE_GL_VOID(glBindFramebufferOES, (GLenum target, GLuint framebuffer), (target, framebuffer), 2, "GLenum", target, "GLuint", framebuffer)
+TRACE_GL_VOID(glBindRenderbufferOES, (GLenum target, GLuint renderbuffer), (target, renderbuffer), 2, "GLenum", target, "GLuint", renderbuffer)
+TRACE_GL_VOID(glBindVertexArrayOES, (GLuint array), (array), 1, "GLuint", array)
+TRACE_GL_VOID(glBlendEquationOES, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glBlendEquationSeparateOES, (GLenum modeRGB, GLenum modeAlpha), (modeRGB, modeAlpha), 2, "GLenum", modeRGB, "GLenum", modeAlpha)
+TRACE_GL_VOID(glBlendFuncSeparateOES, (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha), (srcRGB, dstRGB, srcAlpha, dstAlpha), 4, "GLenum", srcRGB, "GLenum", dstRGB, "GLenum", srcAlpha, "GLenum", dstAlpha)
+TRACE_GL(GLenum, glCheckFramebufferStatusOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glClearColorx, (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha), (red, green, blue, alpha), 4, "GLclampx", red, "GLclampx", green, "GLclampx", blue, "GLclampx", alpha)
+TRACE_GL_VOID(glClearColorxOES, (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha), (red, green, blue, alpha), 4, "GLclampx", red, "GLclampx", green, "GLclampx", blue, "GLclampx", alpha)
+TRACE_GL_VOID(glClearDepthfOES, (GLclampf depth), (depth), 1, "GLclampf", depth)
+TRACE_GL_VOID(glClearDepthx, (GLclampx depth), (depth), 1, "GLclampx", depth)
+TRACE_GL_VOID(glClearDepthxOES, (GLclampx depth), (depth), 1, "GLclampx", depth)
+TRACE_GL_VOID(glClientActiveTexture, (GLenum texture), (texture), 1, "GLenum", texture)
+TRACE_GL_VOID(glClipPlanef, (GLenum plane, const GLfloat *equation), (plane, equation), 2, "GLenum", plane, "const GLfloat *", equation)
+TRACE_GL_VOID(glClipPlanefIMG, (GLenum p, const GLfloat *eqn), (p, eqn), 2, "GLenum", p, "const GLfloat *", eqn)
+TRACE_GL_VOID(glClipPlanefOES, (GLenum plane, const GLfloat *equation), (plane, equation), 2, "GLenum", plane, "const GLfloat *", equation)
+TRACE_GL_VOID(glClipPlanex, (GLenum plane, const GLfixed *equation), (plane, equation), 2, "GLenum", plane, "const GLfixed *", equation)
+TRACE_GL_VOID(glClipPlanexIMG, (GLenum p, const GLfixed *eqn), (p, eqn), 2, "GLenum", p, "const GLfixed *", eqn)
+TRACE_GL_VOID(glClipPlanexOES, (GLenum plane, const GLfixed *equation), (plane, equation), 2, "GLenum", plane, "const GLfixed *", equation)
+TRACE_GL_VOID(glColor4f, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha), (red, green, blue, alpha), 4, "GLfloat", red, "GLfloat", green, "GLfloat", blue, "GLfloat", alpha)
+TRACE_GL_VOID(glColor4ub, (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha), (red, green, blue, alpha), 4, "GLubyte", red, "GLubyte", green, "GLubyte", blue, "GLubyte", alpha)
+TRACE_GL_VOID(glColor4x, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
+TRACE_GL_VOID(glColor4xOES, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
+TRACE_GL_VOID(glColorPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glCompressedTexImage3DOES, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data), (target, level, internalformat, width, height, depth, border, imageSize, data), 9, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLsizei", imageSize, "const GLvoid*", data)
+TRACE_GL_VOID(glCompressedTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLsizei", imageSize, "const GLvoid*", data)
+TRACE_GL_VOID(glCopyTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height), (target, level, xoffset, yoffset, zoffset, x, y, width, height), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glCoverageMaskNV, (GLboolean mask), (mask), 1, "GLboolean", mask)
+TRACE_GL_VOID(glCoverageOperationNV, (GLenum operation), (operation), 1, "GLenum", operation)
+TRACE_GL_VOID(glCurrentPaletteMatrixOES, (GLuint matrixpaletteindex), (matrixpaletteindex), 1, "GLuint", matrixpaletteindex)
+TRACE_GL_VOID(glDeleteFencesNV, (GLsizei n, const GLuint *fences), (n, fences), 2, "GLsizei", n, "const GLuint *", fences)
+TRACE_GL_VOID(glDeleteFramebuffersOES, (GLsizei n, const GLuint* framebuffers), (n, framebuffers), 2, "GLsizei", n, "const GLuint*", framebuffers)
+TRACE_GL_VOID(glDeletePerfMonitorsAMD, (GLsizei n, GLuint *monitors), (n, monitors), 2, "GLsizei", n, "GLuint *", monitors)
+TRACE_GL_VOID(glDeleteRenderbuffersOES, (GLsizei n, const GLuint* renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "const GLuint*", renderbuffers)
+TRACE_GL_VOID(glDeleteVertexArraysOES, (GLsizei n, const GLuint *arrays), (n, arrays), 2, "GLsizei", n, "const GLuint *", arrays)
+TRACE_GL_VOID(glDepthRangefOES, (GLclampf zNear, GLclampf zFar), (zNear, zFar), 2, "GLclampf", zNear, "GLclampf", zFar)
+TRACE_GL_VOID(glDepthRangex, (GLclampx zNear, GLclampx zFar), (zNear, zFar), 2, "GLclampx", zNear, "GLclampx", zFar)
+TRACE_GL_VOID(glDepthRangexOES, (GLclampx zNear, GLclampx zFar), (zNear, zFar), 2, "GLclampx", zNear, "GLclampx", zFar)
+TRACE_GL_VOID(glDisableClientState, (GLenum array), (array), 1, "GLenum", array)
+TRACE_GL_VOID(glDisableDriverControlQCOM, (GLuint driverControl), (driverControl), 1, "GLuint", driverControl)
+TRACE_GL_VOID(glDiscardFramebufferEXT, (GLenum target, GLsizei numAttachments, const GLenum *attachments), (target, numAttachments, attachments), 3, "GLenum", target, "GLsizei", numAttachments, "const GLenum *", attachments)
+TRACE_GL_VOID(glDrawTexfOES, (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height), (x, y, z, width, height), 5, "GLfloat", x, "GLfloat", y, "GLfloat", z, "GLfloat", width, "GLfloat", height)
+TRACE_GL_VOID(glDrawTexfvOES, (const GLfloat *coords), (coords), 1, "const GLfloat *", coords)
+TRACE_GL_VOID(glDrawTexiOES, (GLint x, GLint y, GLint z, GLint width, GLint height), (x, y, z, width, height), 5, "GLint", x, "GLint", y, "GLint", z, "GLint", width, "GLint", height)
+TRACE_GL_VOID(glDrawTexivOES, (const GLint *coords), (coords), 1, "const GLint *", coords)
+TRACE_GL_VOID(glDrawTexsOES, (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height), (x, y, z, width, height), 5, "GLshort", x, "GLshort", y, "GLshort", z, "GLshort", width, "GLshort", height)
+TRACE_GL_VOID(glDrawTexsvOES, (const GLshort *coords), (coords), 1, "const GLshort *", coords)
+TRACE_GL_VOID(glDrawTexxOES, (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height), (x, y, z, width, height), 5, "GLfixed", x, "GLfixed", y, "GLfixed", z, "GLfixed", width, "GLfixed", height)
+TRACE_GL_VOID(glDrawTexxvOES, (const GLfixed *coords), (coords), 1, "const GLfixed *", coords)
+TRACE_GL_VOID(glEGLImageTargetRenderbufferStorageOES, (GLenum target, GLeglImageOES image), (target, image), 2, "GLenum", target, "GLeglImageOES", image)
+TRACE_GL_VOID(glEGLImageTargetTexture2DOES, (GLenum target, GLeglImageOES image), (target, image), 2, "GLenum", target, "GLeglImageOES", image)
+TRACE_GL_VOID(glEnableClientState, (GLenum array), (array), 1, "GLenum", array)
+TRACE_GL_VOID(glEnableDriverControlQCOM, (GLuint driverControl), (driverControl), 1, "GLuint", driverControl)
+TRACE_GL_VOID(glEndPerfMonitorAMD, (GLuint monitor), (monitor), 1, "GLuint", monitor)
+TRACE_GL_VOID(glEndTilingQCOM, (GLbitfield preserveMask), (preserveMask), 1, "GLbitfield", preserveMask)
+TRACE_GL_VOID(glExtGetBufferPointervQCOM, (GLenum target, GLvoid **params), (target, params), 2, "GLenum", target, "GLvoid **", params)
+TRACE_GL_VOID(glExtGetBuffersQCOM, (GLuint *buffers, GLint maxBuffers, GLint *numBuffers), (buffers, maxBuffers, numBuffers), 3, "GLuint *", buffers, "GLint", maxBuffers, "GLint *", numBuffers)
+TRACE_GL_VOID(glExtGetFramebuffersQCOM, (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers), (framebuffers, maxFramebuffers, numFramebuffers), 3, "GLuint *", framebuffers, "GLint", maxFramebuffers, "GLint *", numFramebuffers)
+TRACE_GL_VOID(glExtGetProgramBinarySourceQCOM, (GLuint program, GLenum shadertype, GLchar *source, GLint *length), (program, shadertype, source, length), 4, "GLuint", program, "GLenum", shadertype, "GLchar *", source, "GLint *", length)
+TRACE_GL_VOID(glExtGetProgramsQCOM, (GLuint *programs, GLint maxPrograms, GLint *numPrograms), (programs, maxPrograms, numPrograms), 3, "GLuint *", programs, "GLint", maxPrograms, "GLint *", numPrograms)
+TRACE_GL_VOID(glExtGetRenderbuffersQCOM, (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers), (renderbuffers, maxRenderbuffers, numRenderbuffers), 3, "GLuint *", renderbuffers, "GLint", maxRenderbuffers, "GLint *", numRenderbuffers)
+TRACE_GL_VOID(glExtGetShadersQCOM, (GLuint *shaders, GLint maxShaders, GLint *numShaders), (shaders, maxShaders, numShaders), 3, "GLuint *", shaders, "GLint", maxShaders, "GLint *", numShaders)
+TRACE_GL_VOID(glExtGetTexLevelParameterivQCOM, (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params), (texture, face, level, pname, params), 5, "GLuint", texture, "GLenum", face, "GLint", level, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glExtGetTexSubImageQCOM, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "GLvoid *", texels)
+TRACE_GL_VOID(glExtGetTexturesQCOM, (GLuint *textures, GLint maxTextures, GLint *numTextures), (textures, maxTextures, numTextures), 3, "GLuint *", textures, "GLint", maxTextures, "GLint *", numTextures)
+TRACE_GL(GLboolean, glExtIsProgramBinaryQCOM, (GLuint program), (program), 1, "GLuint", program)
+TRACE_GL_VOID(glExtTexObjectStateOverrideiQCOM, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glFinishFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL_VOID(glFogf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glFogfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glFogx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glFogxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glFogxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glFogxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glFramebufferRenderbufferOES, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment, renderbuffertarget, renderbuffer), 4, "GLenum", target, "GLenum", attachment, "GLenum", renderbuffertarget, "GLuint", renderbuffer)
+TRACE_GL_VOID(glFramebufferTexture2DMultisampleIMG, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples), (target, attachment, textarget, texture, level, samples), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLsizei", samples)
+TRACE_GL_VOID(glFramebufferTexture2DOES, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level), (target, attachment, textarget, texture, level), 5, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level)
+TRACE_GL_VOID(glFramebufferTexture3DOES, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset), (target, attachment, textarget, texture, level, zoffset), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLint", zoffset)
+TRACE_GL_VOID(glFrustumf, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glFrustumfOES, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glFrustumx, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glFrustumxOES, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glGenFencesNV, (GLsizei n, GLuint *fences), (n, fences), 2, "GLsizei", n, "GLuint *", fences)
+TRACE_GL_VOID(glGenFramebuffersOES, (GLsizei n, GLuint* framebuffers), (n, framebuffers), 2, "GLsizei", n, "GLuint*", framebuffers)
+TRACE_GL_VOID(glGenPerfMonitorsAMD, (GLsizei n, GLuint *monitors), (n, monitors), 2, "GLsizei", n, "GLuint *", monitors)
+TRACE_GL_VOID(glGenRenderbuffersOES, (GLsizei n, GLuint* renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "GLuint*", renderbuffers)
+TRACE_GL_VOID(glGenVertexArraysOES, (GLsizei n, GLuint *arrays), (n, arrays), 2, "GLsizei", n, "GLuint *", arrays)
+TRACE_GL_VOID(glGenerateMipmapOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glGetBufferPointervOES, (GLenum target, GLenum pname, GLvoid ** params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLvoid **", params)
+TRACE_GL_VOID(glGetClipPlanef, (GLenum pname, GLfloat eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfloat", eqn)
+TRACE_GL_VOID(glGetClipPlanefOES, (GLenum pname, GLfloat eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfloat", eqn)
+TRACE_GL_VOID(glGetClipPlanex, (GLenum pname, GLfixed eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfixed", eqn)
+TRACE_GL_VOID(glGetClipPlanexOES, (GLenum pname, GLfixed eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfixed", eqn)
+TRACE_GL_VOID(glGetDriverControlStringQCOM, (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString), (driverControl, bufSize, length, driverControlString), 4, "GLuint", driverControl, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", driverControlString)
+TRACE_GL_VOID(glGetDriverControlsQCOM, (GLint *num, GLsizei size, GLuint *driverControls), (num, size, driverControls), 3, "GLint *", num, "GLsizei", size, "GLuint *", driverControls)
+TRACE_GL_VOID(glGetFenceivNV, (GLuint fence, GLenum pname, GLint *params), (fence, pname, params), 3, "GLuint", fence, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetFixedv, (GLenum pname, GLfixed *params), (pname, params), 2, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetFixedvOES, (GLenum pname, GLfixed *params), (pname, params), 2, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetFramebufferAttachmentParameterivOES, (GLenum target, GLenum attachment, GLenum pname, GLint* params), (target, attachment, pname, params), 4, "GLenum", target, "GLenum", attachment, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetLightfv, (GLenum light, GLenum pname, GLfloat *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetLightxv, (GLenum light, GLenum pname, GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetLightxvOES, (GLenum light, GLenum pname, GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetMaterialfv, (GLenum face, GLenum pname, GLfloat *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetMaterialxv, (GLenum face, GLenum pname, GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetMaterialxvOES, (GLenum face, GLenum pname, GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetPerfMonitorCounterDataAMD, (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten), (monitor, pname, dataSize, data, bytesWritten), 5, "GLuint", monitor, "GLenum", pname, "GLsizei", dataSize, "GLuint *", data, "GLint *", bytesWritten)
+TRACE_GL_VOID(glGetPerfMonitorCounterInfoAMD, (GLuint group, GLuint counter, GLenum pname, GLvoid *data), (group, counter, pname, data), 4, "GLuint", group, "GLuint", counter, "GLenum", pname, "GLvoid *", data)
+TRACE_GL_VOID(glGetPerfMonitorCounterStringAMD, (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString), (group, counter, bufSize, length, counterString), 5, "GLuint", group, "GLuint", counter, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", counterString)
+TRACE_GL_VOID(glGetPerfMonitorCountersAMD, (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters), (group, numCounters, maxActiveCounters, counterSize, counters), 5, "GLuint", group, "GLint *", numCounters, "GLint *", maxActiveCounters, "GLsizei", counterSize, "GLuint *", counters)
+TRACE_GL_VOID(glGetPerfMonitorGroupStringAMD, (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString), (group, bufSize, length, groupString), 4, "GLuint", group, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", groupString)
+TRACE_GL_VOID(glGetPerfMonitorGroupsAMD, (GLint *numGroups, GLsizei groupsSize, GLuint *groups), (numGroups, groupsSize, groups), 3, "GLint *", numGroups, "GLsizei", groupsSize, "GLuint *", groups)
+TRACE_GL_VOID(glGetPointerv, (GLenum pname, GLvoid **params), (pname, params), 2, "GLenum", pname, "GLvoid **", params)
+TRACE_GL_VOID(glGetProgramBinaryOES, (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary), (program, bufSize, length, binaryFormat, binary), 5, "GLuint", program, "GLsizei", bufSize, "GLsizei *", length, "GLenum *", binaryFormat, "GLvoid *", binary)
+TRACE_GL_VOID(glGetRenderbufferParameterivOES, (GLenum target, GLenum pname, GLint* params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetTexEnvfv, (GLenum env, GLenum pname, GLfloat *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetTexEnviv, (GLenum env, GLenum pname, GLint *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetTexEnvxv, (GLenum env, GLenum pname, GLfixed *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexEnvxvOES, (GLenum env, GLenum pname, GLfixed *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexGenfvOES, (GLenum coord, GLenum pname, GLfloat *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetTexGenivOES, (GLenum coord, GLenum pname, GLint *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetTexGenxvOES, (GLenum coord, GLenum pname, GLfixed *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexParameterxv, (GLenum target, GLenum pname, GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexParameterxvOES, (GLenum target, GLenum pname, GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
+TRACE_GL(GLboolean, glIsFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL(GLboolean, glIsFramebufferOES, (GLuint framebuffer), (framebuffer), 1, "GLuint", framebuffer)
+TRACE_GL(GLboolean, glIsRenderbufferOES, (GLuint renderbuffer), (renderbuffer), 1, "GLuint", renderbuffer)
+TRACE_GL(GLboolean, glIsVertexArrayOES, (GLuint array), (array), 1, "GLuint", array)
+TRACE_GL_VOID(glLightModelf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glLightModelfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glLightModelx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightModelxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightModelxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightModelxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightf, (GLenum light, GLenum pname, GLfloat param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glLightfv, (GLenum light, GLenum pname, const GLfloat *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glLightx, (GLenum light, GLenum pname, GLfixed param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightxOES, (GLenum light, GLenum pname, GLfixed param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightxv, (GLenum light, GLenum pname, const GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightxvOES, (GLenum light, GLenum pname, const GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLineWidthx, (GLfixed width), (width), 1, "GLfixed", width)
+TRACE_GL_VOID(glLineWidthxOES, (GLfixed width), (width), 1, "GLfixed", width)
+TRACE_GL_VOID(glLoadIdentity, (void), (), 0)
+TRACE_GL_VOID(glLoadMatrixf, (const GLfloat *m), (m), 1, "const GLfloat *", m)
+TRACE_GL_VOID(glLoadMatrixx, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glLoadMatrixxOES, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glLoadPaletteFromModelViewMatrixOES, (void), (), 0)
+TRACE_GL_VOID(glLogicOp, (GLenum opcode), (opcode), 1, "GLenum", opcode)
+TRACE_GL(void*, glMapBufferOES, (GLenum target, GLenum access), (target, access), 2, "GLenum", target, "GLenum", access)
+TRACE_GL_VOID(glMaterialf, (GLenum face, GLenum pname, GLfloat param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glMaterialfv, (GLenum face, GLenum pname, const GLfloat *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glMaterialx, (GLenum face, GLenum pname, GLfixed param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glMaterialxOES, (GLenum face, GLenum pname, GLfixed param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glMaterialxv, (GLenum face, GLenum pname, const GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glMaterialxvOES, (GLenum face, GLenum pname, const GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glMatrixIndexPointerOES, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glMatrixMode, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glMultMatrixf, (const GLfloat *m), (m), 1, "const GLfloat *", m)
+TRACE_GL_VOID(glMultMatrixx, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glMultMatrixxOES, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glMultiDrawArraysEXT, (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount), (mode, first, count, primcount), 4, "GLenum", mode, "GLint *", first, "GLsizei *", count, "GLsizei", primcount)
+TRACE_GL_VOID(glMultiDrawElementsEXT, (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount), (mode, count, type, indices, primcount), 5, "GLenum", mode, "const GLsizei *", count, "GLenum", type, "const GLvoid* *", indices, "GLsizei", primcount)
+TRACE_GL_VOID(glMultiTexCoord4f, (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q), (target, s, t, r, q), 5, "GLenum", target, "GLfloat", s, "GLfloat", t, "GLfloat", r, "GLfloat", q)
+TRACE_GL_VOID(glMultiTexCoord4x, (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q), (target, s, t, r, q), 5, "GLenum", target, "GLfixed", s, "GLfixed", t, "GLfixed", r, "GLfixed", q)
+TRACE_GL_VOID(glMultiTexCoord4xOES, (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q), (target, s, t, r, q), 5, "GLenum", target, "GLfixed", s, "GLfixed", t, "GLfixed", r, "GLfixed", q)
+TRACE_GL_VOID(glNormal3f, (GLfloat nx, GLfloat ny, GLfloat nz), (nx, ny, nz), 3, "GLfloat", nx, "GLfloat", ny, "GLfloat", nz)
+TRACE_GL_VOID(glNormal3x, (GLfixed nx, GLfixed ny, GLfixed nz), (nx, ny, nz), 3, "GLfixed", nx, "GLfixed", ny, "GLfixed", nz)
+TRACE_GL_VOID(glNormal3xOES, (GLfixed nx, GLfixed ny, GLfixed nz), (nx, ny, nz), 3, "GLfixed", nx, "GLfixed", ny, "GLfixed", nz)
+TRACE_GL_VOID(glNormalPointer, (GLenum type, GLsizei stride, const GLvoid *pointer), (type, stride, pointer), 3, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glOrthof, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glOrthofOES, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glOrthox, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glOrthoxOES, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glPointParameterf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glPointParameterfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glPointParameterx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glPointParameterxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glPointParameterxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glPointParameterxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glPointSize, (GLfloat size), (size), 1, "GLfloat", size)
+TRACE_GL_VOID(glPointSizePointerOES, (GLenum type, GLsizei stride, const GLvoid *pointer), (type, stride, pointer), 3, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glPointSizex, (GLfixed size), (size), 1, "GLfixed", size)
+TRACE_GL_VOID(glPointSizexOES, (GLfixed size), (size), 1, "GLfixed", size)
+TRACE_GL_VOID(glPolygonOffsetx, (GLfixed factor, GLfixed units), (factor, units), 2, "GLfixed", factor, "GLfixed", units)
+TRACE_GL_VOID(glPolygonOffsetxOES, (GLfixed factor, GLfixed units), (factor, units), 2, "GLfixed", factor, "GLfixed", units)
+TRACE_GL_VOID(glPopMatrix, (void), (), 0)
+TRACE_GL_VOID(glProgramBinaryOES, (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length), (program, binaryFormat, binary, length), 4, "GLuint", program, "GLenum", binaryFormat, "const GLvoid *", binary, "GLint", length)
+TRACE_GL_VOID(glPushMatrix, (void), (), 0)
+TRACE_GL(GLbitfield, glQueryMatrixxOES, (GLfixed mantissa[16], GLint exponent[16]), (mantissa, exponent), 2, "GLfixed", mantissa, "GLint", exponent)
+TRACE_GL_VOID(glRenderbufferStorageMultisampleIMG, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glRenderbufferStorageOES, (GLenum target, GLenum internalformat, GLsizei width, GLsizei height), (target, internalformat, width, height), 4, "GLenum", target, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glRotatef, (GLfloat angle, GLfloat x, GLfloat y, GLfloat z), (angle, x, y, z), 4, "GLfloat", angle, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glRotatex, (GLfixed angle, GLfixed x, GLfixed y, GLfixed z), (angle, x, y, z), 4, "GLfixed", angle, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glRotatexOES, (GLfixed angle, GLfixed x, GLfixed y, GLfixed z), (angle, x, y, z), 4, "GLfixed", angle, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glSampleCoveragex, (GLclampx value, GLboolean invert), (value, invert), 2, "GLclampx", value, "GLboolean", invert)
+TRACE_GL_VOID(glSampleCoveragexOES, (GLclampx value, GLboolean invert), (value, invert), 2, "GLclampx", value, "GLboolean", invert)
+TRACE_GL_VOID(glScalef, (GLfloat x, GLfloat y, GLfloat z), (x, y, z), 3, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glScalex, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glScalexOES, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glSelectPerfMonitorCountersAMD, (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList), (monitor, enable, group, numCounters, countersList), 5, "GLuint", monitor, "GLboolean", enable, "GLuint", group, "GLint", numCounters, "GLuint *", countersList)
+TRACE_GL_VOID(glSetFenceNV, (GLuint fence, GLenum condition), (fence, condition), 2, "GLuint", fence, "GLenum", condition)
+TRACE_GL_VOID(glShadeModel, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glStartTilingQCOM, (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask), (x, y, width, height, preserveMask), 5, "GLuint", x, "GLuint", y, "GLuint", width, "GLuint", height, "GLbitfield", preserveMask)
+TRACE_GL(GLboolean, glTestFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL_VOID(glTexCoordPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glTexEnvf, (GLenum target, GLenum pname, GLfloat param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glTexEnvfv, (GLenum target, GLenum pname, const GLfloat *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glTexEnvi, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glTexEnviv, (GLenum target, GLenum pname, const GLint *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLint *", params)
+TRACE_GL_VOID(glTexEnvx, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexEnvxOES, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexEnvxv, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexEnvxvOES, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexGenfOES, (GLenum coord, GLenum pname, GLfloat param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glTexGenfvOES, (GLenum coord, GLenum pname, const GLfloat *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glTexGeniOES, (GLenum coord, GLenum pname, GLint param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glTexGenivOES, (GLenum coord, GLenum pname, const GLint *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLint *", params)
+TRACE_GL_VOID(glTexGenxOES, (GLenum coord, GLenum pname, GLfixed param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexGenxvOES, (GLenum coord, GLenum pname, const GLfixed *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexImage3DOES, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels), (target, level, internalformat, width, height, depth, border, format, type, pixels), 10, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLenum", format, "GLenum", type, "const GLvoid*", pixels)
+TRACE_GL_VOID(glTexParameterx, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexParameterxOES, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexParameterxv, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexParameterxvOES, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "const GLvoid*", pixels)
+TRACE_GL_VOID(glTranslatef, (GLfloat x, GLfloat y, GLfloat z), (x, y, z), 3, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glTranslatex, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glTranslatexOES, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL(GLboolean, glUnmapBufferOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glVertexPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glWeightPointerOES, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index c8f529a..a809316 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -29,16 +29,6 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-struct egl_connection_t
-{
-    inline egl_connection_t() : dso(0) { }
-    void *              dso;
-    gl_hooks_t *        hooks[2];
-    EGLint              major;
-    EGLint              minor;
-    egl_t               egl;
-};
-
 EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/glesv2dbg.h b/opengl/libs/glesv2dbg.h
new file mode 100644
index 0000000..44bc288
--- /dev/null
+++ b/opengl/libs/glesv2dbg.h
@@ -0,0 +1,38 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef _GLESV2_DBG_H_
+#define _GLESV2_DBG_H_
+
+#include <pthread.h>
+
+namespace android
+{
+struct DbgContext;
+
+DbgContext* CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks);
+
+void dbgReleaseThread();
+
+// create and bind socket if haven't already, if failed to create socket or
+//  forceUseFile, then open /data/local/tmp/dump.gles2dbg, exit when size reached
+void StartDebugServer(const unsigned short port, const bool forceUseFile,
+                      const unsigned int maxFileSize, const char * const filePath);
+void StopDebugServer(); // close socket if open
+
+}; // namespace android
+
+#endif // #ifndef _GLESV2_DBG_H_
diff --git a/opengl/libs/glesv2dbg_functions.h b/opengl/libs/glesv2dbg_functions.h
new file mode 100644
index 0000000..2d70032
--- /dev/null
+++ b/opengl/libs/glesv2dbg_functions.h
@@ -0,0 +1,381 @@
+extern "C"
+{
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
+GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const GLchar* name)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBindVertexArrayOES, GLuint array)
+GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glBlendEquation,  GLenum mode )
+GL_ENTRY(void, glBlendEquationOES, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
+GL_ENTRY(void, glBlendFuncSeparate, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
+GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
+GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearDepthf, GLclampf depth)
+GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
+GL_ENTRY(void, glClearDepthx, GLclampx depth)
+GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
+GL_ENTRY(void, glClearStencil, GLint s)
+GL_ENTRY(void, glClientActiveTexture, GLenum texture)
+GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanefIMG, GLenum p, const GLfloat *eqn)
+GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glClipPlanexIMG, GLenum p, const GLfixed *eqn)
+GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glCompileShader, GLuint shader)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
+GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCoverageMaskNV, GLboolean mask)
+GL_ENTRY(void, glCoverageOperationNV, GLenum operation)
+GL_ENTRY(GLuint, glCreateProgram, void)
+GL_ENTRY(GLuint, glCreateShader, GLenum type)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
+GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glDeleteProgram, GLuint program)
+GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteShader, GLuint shader)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDeleteVertexArraysOES, GLsizei n, const GLuint *arrays)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableClientState, GLenum array)
+GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDiscardFramebufferEXT, GLenum target, GLsizei numAttachments, const GLenum *attachments)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
+GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
+GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
+GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
+GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
+GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableClientState, GLenum array)
+GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glEndTilingQCOM, GLbitfield preserveMask)
+GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, GLvoid **params)
+GL_ENTRY(void, glExtGetBuffersQCOM, GLuint *buffers, GLint maxBuffers, GLint *numBuffers)
+GL_ENTRY(void, glExtGetFramebuffersQCOM, GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers)
+GL_ENTRY(void, glExtGetProgramBinarySourceQCOM, GLuint program, GLenum shadertype, GLchar *source, GLint *length)
+GL_ENTRY(void, glExtGetProgramsQCOM, GLuint *programs, GLint maxPrograms, GLint *numPrograms)
+GL_ENTRY(void, glExtGetRenderbuffersQCOM, GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers)
+GL_ENTRY(void, glExtGetShadersQCOM, GLuint *shaders, GLint maxShaders, GLint *numShaders)
+GL_ENTRY(void, glExtGetTexLevelParameterivQCOM, GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params)
+GL_ENTRY(void, glExtGetTexSubImageQCOM, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels)
+GL_ENTRY(void, glExtGetTexturesQCOM, GLuint *textures, GLint maxTextures, GLint *numTextures)
+GL_ENTRY(GLboolean, glExtIsProgramBinaryQCOM, GLuint program)
+GL_ENTRY(void, glExtTexObjectStateOverrideiQCOM, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFinishFenceNV, GLuint fence)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture2DMultisampleIMG, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
+GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+GL_ENTRY(void, glFrontFace, GLenum mode)
+GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
+GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGenVertexArraysOES, GLsizei n, GLuint *arrays)
+GL_ENTRY(void, glGenerateMipmap, GLenum target)
+GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+GL_ENTRY(int, glGetAttribLocation, GLuint program, const GLchar* name)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, GLvoid ** params)
+GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString)
+GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
+GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, GLvoid *data)
+GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString)
+GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
+GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString)
+GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
+GL_ENTRY(void, glGetPointerv, GLenum pname, GLvoid **params)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
+GL_ENTRY(const GLubyte *, glGetString, GLenum name)
+GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(int, glGetUniformLocation, GLuint program, const GLchar* name)
+GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
+GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, GLvoid** pointer)
+GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
+GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
+GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsProgram, GLuint program)
+GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsShader, GLuint shader)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(GLboolean, glIsVertexArrayOES, GLuint array)
+GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLineWidthx, GLfixed width)
+GL_ENTRY(void, glLineWidthxOES, GLfixed width)
+GL_ENTRY(void, glLinkProgram, GLuint program)
+GL_ENTRY(void, glLoadIdentity, void)
+GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
+GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
+GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
+GL_ENTRY(void, glLogicOp, GLenum opcode)
+GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
+GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glMatrixMode, GLenum mode)
+GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
+GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiDrawArraysEXT, GLenum mode, GLint *first, GLsizei *count, GLsizei primcount)
+GL_ENTRY(void, glMultiDrawElementsEXT, GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount)
+GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
+GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointSize, GLfloat size)
+GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glPointSizex, GLfixed size)
+GL_ENTRY(void, glPointSizexOES, GLfixed size)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPopMatrix, void)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length)
+GL_ENTRY(void, glPushMatrix, void)
+GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
+GL_ENTRY(void, glReleaseShaderCompiler, void)
+GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageMultisampleIMG, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
+GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
+GL_ENTRY(void, glShadeModel, GLenum mode)
+GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+GL_ENTRY(void, glStartTilingQCOM, GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask)
+GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilMask, GLuint mask)
+GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
+GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
+GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
+GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
+GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glUniform1f, GLint location, GLfloat x)
+GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform1i, GLint location, GLint x)
+GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform2f, GLint location, GLfloat x, GLfloat y)
+GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform2i, GLint location, GLint x, GLint y)
+GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform3f, GLint location, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform3i, GLint location, GLint x, GLint y, GLint z)
+GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform4f, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform4i, GLint location, GLint x, GLint y, GLint z, GLint w)
+GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glUseProgram, GLuint program)
+GL_ENTRY(void, glValidateProgram, GLuint program)
+GL_ENTRY(void, glVertexAttrib1f, GLuint indx, GLfloat x)
+GL_ENTRY(void, glVertexAttrib1fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib2f, GLuint indx, GLfloat x, GLfloat y)
+GL_ENTRY(void, glVertexAttrib2fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+
+
+}
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 812e26d..7ac88cd 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -54,22 +54,6 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-//  EGLDisplay are global, not attached to a given thread
-const unsigned int NUM_DISPLAYS = 1;
-
-enum {
-    IMPL_HARDWARE = 0,
-    IMPL_SOFTWARE,
-    IMPL_NUM_IMPLEMENTATIONS
-};
-
-enum {
-    GLESv1_INDEX = 0,
-    GLESv2_INDEX = 1,
-};
-
-// ----------------------------------------------------------------------------
-
 // GL / EGL hooks
 
 #undef GL_ENTRY
@@ -92,60 +76,8 @@
 #undef GL_ENTRY
 #undef EGL_ENTRY
 
-
-// ----------------------------------------------------------------------------
-
-extern gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
-extern gl_hooks_t gHooksNoContext;
-extern pthread_key_t gGLWrapperKey;
-extern "C" void gl_unimplemented();
-
-extern char const * const gl_names[];
-extern char const * const egl_names[];
-
-// ----------------------------------------------------------------------------
-
-#if USE_FAST_TLS_KEY
-
-// We have a dedicated TLS slot in bionic
-static inline gl_hooks_t const * volatile * get_tls_hooks() {
-    volatile void *tls_base = __get_tls();
-    gl_hooks_t const * volatile * tls_hooks = 
-            reinterpret_cast<gl_hooks_t const * volatile *>(tls_base);
-    return tls_hooks;
-}
-
-static inline void setGlThreadSpecific(gl_hooks_t const *value) {
-    gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
-    tls_hooks[TLS_SLOT_OPENGL_API] = value;
-}
-
-static gl_hooks_t const* getGlThreadSpecific() {
-    gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
-    gl_hooks_t const* hooks = tls_hooks[TLS_SLOT_OPENGL_API];
-    if (hooks) return hooks;
-    return &gHooksNoContext;
-}
-
-#else
-
-static inline void setGlThreadSpecific(gl_hooks_t const *value) {
-    pthread_setspecific(gGLWrapperKey, value);
-}
-
-static gl_hooks_t const* getGlThreadSpecific() {
-    gl_hooks_t const* hooks =  static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey));
-    if (hooks) return hooks;
-    return &gHooksNoContext;
-}
-
-#endif
-
-#if EGL_TRACE
-
-extern gl_hooks_t const* getGLTraceThreadSpecific();
-
-#endif
+EGLAPI void setGlThreadSpecific(gl_hooks_t const *value);
+EGLAPI gl_hooks_t const* getGlThreadSpecific();
 
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/opengl/tests/gl2_cameraeye/Android.mk b/opengl/tests/gl2_cameraeye/Android.mk
new file mode 100644
index 0000000..4a43a9e
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := GL2CameraEye
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/opengl/tests/gl2_cameraeye/AndroidManifest.xml b/opengl/tests/gl2_cameraeye/AndroidManifest.xml
new file mode 100644
index 0000000..c53f7be
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Declare the contents of this Android application.  The namespace
+     attribute brings in the Android platform namespace, and the package
+     supplies a unique name for the application.  When writing your
+     own application, the package name must be changed from "com.example.*"
+     to come from a domain that you own or have control over. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.gl2cameraeye">
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:name="android.hardware.camera.autofocus" />
+    <uses-feature android:glEsVersion="0x00020000" />
+    <application android:label="@string/gl2cameraeye_name">
+        <activity android:name="GL2CameraEye">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/opengl/tests/gl2_cameraeye/res/values/strings.xml b/opengl/tests/gl2_cameraeye/res/values/strings.xml
new file mode 100644
index 0000000..386b930
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+
+    <string name="gl2cameraeye_name">GL2CameraEye</string>
+
+</resources>
diff --git a/opengl/tests/gl2_cameraeye/src/com/android/gl2cameraeye/GL2CameraEye.java b/opengl/tests/gl2_cameraeye/src/com/android/gl2cameraeye/GL2CameraEye.java
new file mode 100644
index 0000000..561e4c5
--- /dev/null
+++ b/opengl/tests/gl2_cameraeye/src/com/android/gl2cameraeye/GL2CameraEye.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gl2cameraeye;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.content.pm.ActivityInfo;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.content.Context;
+import android.util.Log;
+
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLUtils;
+import android.opengl.Matrix;
+
+import android.graphics.SurfaceTexture;
+
+import android.hardware.Camera;
+import android.hardware.SensorManager;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.Sensor;
+
+public class GL2CameraEye extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mGLView = new CamGLSurfaceView(this);
+        setContentView(mGLView);
+        setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mGLView.onPause();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mGLView.onResume();
+    }
+
+    private GLSurfaceView mGLView;
+}
+
+class CamGLSurfaceView extends GLSurfaceView implements SensorEventListener {
+    public CamGLSurfaceView(Context context) {
+        super(context);
+        setEGLContextClientVersion(2);
+        mRenderer = new CamRenderer(context);
+        setRenderer(mRenderer);
+
+        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+        mAcceleration = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
+    }
+
+    public boolean onTouchEvent(final MotionEvent event) {
+        queueEvent(new Runnable(){
+                public void run() {
+                mRenderer.setPosition(event.getX() / getWidth(),
+                                      event.getY() / getHeight());
+            }});
+        return true;
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mCamera.stopPreview();
+        mCamera.release();
+
+        mSensorManager.unregisterListener(this);
+    }
+
+    @Override
+    public void onResume() {
+        mCamera = Camera.open();
+        Camera.Parameters p = mCamera.getParameters();
+        // No changes to default camera parameters
+        mCamera.setParameters(p);
+
+        queueEvent(new Runnable(){
+                public void run() {
+                    mRenderer.setCamera(mCamera);
+                }});
+
+        mSensorManager.registerListener(this, mAcceleration, SensorManager.SENSOR_DELAY_GAME);
+        super.onResume();
+    }
+
+    public void onSensorChanged(SensorEvent event) {
+        if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
+            final float[] accelerationVector = event.values;
+            queueEvent(new Runnable(){
+                    public void run() {
+                        mRenderer.setAcceleration(accelerationVector);
+                    }});
+        }
+    }
+
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        // Ignoring sensor accuracy changes.
+    }
+
+    CamRenderer mRenderer;
+    Camera mCamera;
+
+    SensorManager mSensorManager;
+    Sensor mAcceleration;
+}
+
+class CamRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
+
+    public CamRenderer(Context context) {
+        mContext = context;
+
+        mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length
+                * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mTriangleVertices.put(mTriangleVerticesData).position(0);
+
+        Matrix.setIdentityM(mSTMatrix, 0);
+        Matrix.setIdentityM(mMMatrix, 0);
+
+        float[] defaultAcceleration = {0.f,0.f,0.f};
+        setAcceleration(defaultAcceleration);
+        mPos[0] = 0.f;
+        mPos[1] = 0.f;
+        mPos[2] = 0.f;
+        mVel[0] = 0.f;
+        mVel[1] = 0.f;
+        mVel[2] = 0.f;
+
+    }
+
+    /* The following set methods are not synchronized, so should only
+     * be called within the rendering thread context. Use GLSurfaceView.queueEvent for safe access.
+     */
+    public void setPosition(float x, float y) {
+        /* Map from screen (0,0)-(1,1) to scene coordinates */
+        mPos[0] = (x*2-1)*mRatio;
+        mPos[1] = (-y)*2+1;
+        mPos[2] = 0.f;
+        mVel[0] = 0;
+        mVel[1] = 0;
+        mVel[2] = 0;
+    }
+
+    public void setCamera(Camera camera) {
+        mCamera = camera;
+        Camera.Size previewSize = camera.getParameters().getPreviewSize();
+        mCameraRatio = (float)previewSize.width/previewSize.height;
+    }
+
+    public void setAcceleration(float[] accelerationVector) {
+        mGForce[0] = accelerationVector[0];
+        mGForce[1] = accelerationVector[1];
+        mGForce[2] = accelerationVector[2];
+    }
+
+    public void onDrawFrame(GL10 glUnused) {
+        synchronized(this) {
+            if (updateSurface) {
+                mSurface.updateTexImage();
+
+                mSurface.getTransformMatrix(mSTMatrix);
+                long timestamp = mSurface.getTimestamp();
+                doPhysics(timestamp);
+
+                updateSurface = false;
+            }
+        }
+
+        // Ignore the passed-in GL10 interface, and use the GLES20
+        // class's static methods instead.
+        GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+        GLES20.glUseProgram(mProgram);
+        checkGlError("glUseProgram");
+
+        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+        GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
+
+        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
+                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+        checkGlError("glVertexAttribPointer maPosition");
+        GLES20.glEnableVertexAttribArray(maPositionHandle);
+        checkGlError("glEnableVertexAttribArray maPositionHandle");
+
+        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+        GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, false,
+                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+        checkGlError("glVertexAttribPointer maTextureHandle");
+        GLES20.glEnableVertexAttribArray(maTextureHandle);
+        checkGlError("glEnableVertexAttribArray maTextureHandle");
+
+        Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
+        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
+
+        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
+        GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
+        GLES20.glUniform1f(muCRatioHandle, mCameraRatio);
+
+        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+        checkGlError("glDrawArrays");
+    }
+
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
+        // Ignore the passed-in GL10 interface, and use the GLES20
+        // class's static methods instead.
+        GLES20.glViewport(0, 0, width, height);
+        mRatio = (float) width / height;
+        Matrix.frustumM(mProjMatrix, 0, -mRatio, mRatio, -1, 1, 3, 7);
+    }
+
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
+        // Ignore the passed-in GL10 interface, and use the GLES20
+        // class's static methods instead.
+
+        /* Set up alpha blending and an Android background color */
+        GLES20.glEnable(GLES20.GL_BLEND);
+        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
+        GLES20.glClearColor(0.643f, 0.776f, 0.223f, 1.0f);
+
+        /* Set up shaders and handles to their variables */
+        mProgram = createProgram(mVertexShader, mFragmentShader);
+        if (mProgram == 0) {
+            return;
+        }
+        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
+        checkGlError("glGetAttribLocation aPosition");
+        if (maPositionHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for aPosition");
+        }
+        maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
+        checkGlError("glGetAttribLocation aTextureCoord");
+        if (maTextureHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for aTextureCoord");
+        }
+
+        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+        checkGlError("glGetUniformLocation uMVPMatrix");
+        if (muMVPMatrixHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for uMVPMatrix");
+        }
+
+        muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
+        checkGlError("glGetUniformLocation uSTMatrix");
+        if (muMVPMatrixHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for uSTMatrix");
+        }
+
+        muCRatioHandle = GLES20.glGetUniformLocation(mProgram, "uCRatio");
+        checkGlError("glGetUniformLocation uCRatio");
+        if (muMVPMatrixHandle == -1) {
+            throw new RuntimeException("Could not get attrib location for uCRatio");
+        }
+
+        /*
+         * Create our texture. This has to be done each time the
+         * surface is created.
+         */
+
+        int[] textures = new int[1];
+        GLES20.glGenTextures(1, textures, 0);
+
+        mTextureID = textures[0];
+        GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
+        checkGlError("glBindTexture mTextureID");
+
+        // Can't do mipmapping with camera source
+        GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
+                GLES20.GL_NEAREST);
+        GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
+                GLES20.GL_LINEAR);
+        // Clamp to edge is the only option
+        GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
+                GLES20.GL_CLAMP_TO_EDGE);
+        GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
+                GLES20.GL_CLAMP_TO_EDGE);
+        checkGlError("glTexParameteri mTextureID");
+
+        /*
+         * Create the SurfaceTexture that will feed this textureID, and pass it to the camera
+         */
+
+        mSurface = new SurfaceTexture(mTextureID);
+        mSurface.setOnFrameAvailableListener(this);
+        try {
+            mCamera.setPreviewTexture(mSurface);
+        } catch (IOException t) {
+            Log.e(TAG, "Cannot set preview texture target!");
+        }
+
+        /* Start the camera */
+        mCamera.startPreview();
+
+        Matrix.setLookAtM(mVMatrix, 0, 0, 0, 5f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+
+        mLastTime = 0;
+
+        synchronized(this) {
+            updateSurface = false;
+        }
+    }
+
+    synchronized public void onFrameAvailable(SurfaceTexture surface) {
+        /* For simplicity, SurfaceTexture calls here when it has new
+         * data available.  Call may come in from some random thread,
+         * so let's be safe and use synchronize. No OpenGL calls can be done here.
+         */
+        updateSurface = true;
+    }
+
+    private void doPhysics(long timestamp) {
+        /*
+         * Move the camera surface around based on some simple spring physics with drag
+         */
+
+        if (mLastTime == 0)
+            mLastTime = timestamp;
+
+        float deltaT = (timestamp - mLastTime)/1000000000.f; // To seconds
+
+        float springStrength = 20.f;
+        float frictionCoeff = 10.f;
+        float mass = 10.f;
+        float gMultiplier = 4.f;
+        /* Only update physics every 30 ms */
+        if (deltaT > 0.030f) {
+            mLastTime = timestamp;
+
+            float[] totalForce = new float[3];
+            totalForce[0] = -mPos[0] * springStrength - mVel[0]*frictionCoeff + gMultiplier*mGForce[0]*mass;
+            totalForce[1] = -mPos[1] * springStrength - mVel[1]*frictionCoeff + gMultiplier*mGForce[1]*mass;
+            totalForce[2] = -mPos[2] * springStrength - mVel[2]*frictionCoeff + gMultiplier*mGForce[2]*mass;
+
+            float[] accel = new float[3];
+            accel[0] = totalForce[0]/mass;
+            accel[1] = totalForce[1]/mass;
+            accel[2] = totalForce[2]/mass;
+
+            /* Not a very accurate integrator */
+            mVel[0] = mVel[0] + accel[0]*deltaT;
+            mVel[1] = mVel[1] + accel[1]*deltaT;
+            mVel[2] = mVel[2] + accel[2]*deltaT;
+
+            mPos[0] = mPos[0] + mVel[0]*deltaT;
+            mPos[1] = mPos[1] + mVel[1]*deltaT;
+            mPos[2] = mPos[2] + mVel[2]*deltaT;
+
+            Matrix.setIdentityM(mMMatrix, 0);
+            Matrix.translateM(mMMatrix, 0, mPos[0], mPos[1], mPos[2]);
+        }
+
+    }
+
+    private int loadShader(int shaderType, String source) {
+        int shader = GLES20.glCreateShader(shaderType);
+        if (shader != 0) {
+            GLES20.glShaderSource(shader, source);
+            GLES20.glCompileShader(shader);
+            int[] compiled = new int[1];
+            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+            if (compiled[0] == 0) {
+                Log.e(TAG, "Could not compile shader " + shaderType + ":");
+                Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
+                GLES20.glDeleteShader(shader);
+                shader = 0;
+            }
+        }
+        return shader;
+    }
+
+    private int createProgram(String vertexSource, String fragmentSource) {
+        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+        if (vertexShader == 0) {
+            return 0;
+        }
+        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+        if (pixelShader == 0) {
+            return 0;
+        }
+
+        int program = GLES20.glCreateProgram();
+        if (program != 0) {
+            GLES20.glAttachShader(program, vertexShader);
+            checkGlError("glAttachShader");
+            GLES20.glAttachShader(program, pixelShader);
+            checkGlError("glAttachShader");
+            GLES20.glLinkProgram(program);
+            int[] linkStatus = new int[1];
+            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+            if (linkStatus[0] != GLES20.GL_TRUE) {
+                Log.e(TAG, "Could not link program: ");
+                Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+                GLES20.glDeleteProgram(program);
+                program = 0;
+            }
+        }
+        return program;
+    }
+
+    private void checkGlError(String op) {
+        int error;
+        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+            Log.e(TAG, op + ": glError " + error);
+            throw new RuntimeException(op + ": glError " + error);
+        }
+    }
+
+    private static final int FLOAT_SIZE_BYTES = 4;
+    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+    private final float[] mTriangleVerticesData = {
+        // X, Y, Z, U, V
+        -1.0f, -1.0f, 0, 0.f, 0.f,
+        1.0f, -1.0f, 0, 1.f, 0.f,
+        -1.0f,  1.0f, 0, 0.f, 1.f,
+        1.0f,   1.0f, 0, 1.f, 1.f,
+    };
+
+    private FloatBuffer mTriangleVertices;
+
+    private final String mVertexShader =
+        "uniform mat4 uMVPMatrix;\n" +
+        "uniform mat4 uSTMatrix;\n" +
+        "uniform float uCRatio;\n" +
+        "attribute vec4 aPosition;\n" +
+        "attribute vec4 aTextureCoord;\n" +
+        "varying vec2 vTextureCoord;\n" +
+        "varying vec2 vTextureNormCoord;\n" +
+        "void main() {\n" +
+        "  vec4 scaledPos = aPosition;\n" +
+        "  scaledPos.x = scaledPos.x * uCRatio;\n" +
+        "  gl_Position = uMVPMatrix * scaledPos;\n" +
+        "  vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
+        "  vTextureNormCoord = aTextureCoord.xy;\n" +
+        "}\n";
+
+    private final String mFragmentShader =
+        "#extension GL_OES_EGL_image_external : require\n" +
+        "precision mediump float;\n" +
+        "varying vec2 vTextureCoord;\n" +
+        "varying vec2 vTextureNormCoord;\n" +
+        "uniform samplerExternalOES sTexture;\n" +
+        "void main() {\n" +
+        "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
+        "  gl_FragColor.a = 1.0-min(length(vTextureNormCoord-0.5)*2.0,1.0);\n" +
+        "}\n";
+
+    private float[] mMVPMatrix = new float[16];
+    private float[] mProjMatrix = new float[16];
+    private float[] mMMatrix = new float[16];
+    private float[] mVMatrix = new float[16];
+    private float[] mSTMatrix = new float[16];
+
+    private int mProgram;
+    private int mTextureID;
+    private int muMVPMatrixHandle;
+    private int muSTMatrixHandle;
+    private int muCRatioHandle;
+    private int maPositionHandle;
+    private int maTextureHandle;
+
+    private float mRatio = 1.0f;
+    private float mCameraRatio = 1.0f;
+    private float[] mVel = new float[3];
+    private float[] mPos = new float[3];
+    private float[] mGForce = new float[3];
+
+    private long mLastTime;
+
+    private SurfaceTexture mSurface;
+    private Camera mCamera;
+    private boolean updateSurface = false;
+
+    private Context mContext;
+    private static String TAG = "CamRenderer";
+
+    // Magic key
+    private static int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
+}
diff --git a/opengl/tests/gl2_jni/Android.mk b/opengl/tests/gl2_jni/Android.mk
index 384966c..e8b6c57 100644
--- a/opengl/tests/gl2_jni/Android.mk
+++ b/opengl/tests/gl2_jni/Android.mk
@@ -44,7 +44,7 @@
 
 LOCAL_MODULE := libgl2jni
 
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/opengl/tests/gl_jni/Android.mk b/opengl/tests/gl_jni/Android.mk
index f1bd31d..4acd91f 100644
--- a/opengl/tests/gl_jni/Android.mk
+++ b/opengl/tests/gl_jni/Android.mk
@@ -46,7 +46,7 @@
 
 LOCAL_ARM_MODE := arm
 
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/opengl/tests/gl_perfapp/Android.mk b/opengl/tests/gl_perfapp/Android.mk
index dd75a74..4b79569 100644
--- a/opengl/tests/gl_perfapp/Android.mk
+++ b/opengl/tests/gl_perfapp/Android.mk
@@ -47,7 +47,7 @@
 
 LOCAL_MODULE := libglperf
 
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/opengl/tests/gldual/Android.mk b/opengl/tests/gldual/Android.mk
index 995a5d7..f1a998a 100644
--- a/opengl/tests/gldual/Android.mk
+++ b/opengl/tests/gldual/Android.mk
@@ -44,7 +44,7 @@
 
 LOCAL_MODULE := libgldualjni
 
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index 6312970..e4d7e28 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -29,7 +29,7 @@
 
 LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
 LOCAL_STATIC_LIBRARIES += libglTest
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_STATIC_LIBRARY)
 
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
index 7542ac4..ac1e183 100644
--- a/opengl/tests/lib/Android.mk
+++ b/opengl/tests/lib/Android.mk
@@ -27,6 +27,6 @@
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 6c1a231..31f4190 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -21,7 +21,7 @@
 echo "package android.graphics;" > out/android/graphics/Canvas.java
 echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
 
-echo "package android.app; import android.content.pm.IPackageManager; public class ActivityThread { public static final ActivityThread currentActivityThread() { return null; } public static final String currentPackageName(){ return null; } public static IPackageManager getPackageManager() { return null;} }" > out/android/app/ActivityThread.java
+echo "package android.app; import android.content.pm.IPackageManager; public class AppGlobals { public static IPackageManager getPackageManager() { return null;} }" > out/android/app/AppGlobals.java
 # echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
 echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
 echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
diff --git a/opengl/tools/glgen/specs/gles11/checks.spec b/opengl/tools/glgen/specs/gles11/checks.spec
index f917128..f478a32 100644
--- a/opengl/tools/glgen/specs/gles11/checks.spec
+++ b/opengl/tools/glgen/specs/gles11/checks.spec
@@ -31,28 +31,12 @@
 glDrawTexivOES check coords 5
 glDrawTexsvOES check coords 5
 glDrawTexxvOES check coords 5
-glBindFramebufferOES unsupported
-glBindRenderbufferOES unsupported
-glBlendEquation unsupported
-glBlendEquationSeparate unsupported
-glBlendFuncSeparate unsupported
-glCheckFramebufferStatusOES unsupported return 0
-glDeleteFramebuffersOES unsupported
-glDeleteRenderbuffersOES unsupported
-glFramebufferRenderbufferOES unsupported
-glFramebufferStorageOES unsupported
-glFramebufferTexture2DOES unsupported
-glGenFramebuffersOES unsupported
-glGenRenderbuffersOES unsupported
-glGenerateMipmapOES unsupported
-glGetBufferParameter unsupported
-glGetFramebufferAttachmentParameterivOES unsupported
-glGetRenderbufferParameterivOES unsupported
-glGetTexGen unsupported
-glIsFramebufferOES unsupported return JNI_FALSE
-glIsRenderbufferOES unsupported return JNI_FALSE
-glRenderbufferStorageOES unsupported return false
-glTexGen unsupported
-glTexGenf unsupported
-glTexGeni unsupported
-glTexGenx unsupported
+glDeleteFramebuffersOES check framebuffers n
+glDeleteRenderbuffersOES check renderbuffers n
+glGenFramebuffersOES check framebuffers n
+glGenRenderbuffersOES check renderbuffers n
+glGetBufferParameter check params 1
+glGetFramebufferAttachmentParameterivOES check params 1
+glGetRenderbufferParameterivOES check params 1
+glGetTexGen ifcheck params 1 pname GL_TEXTURE_GEN_MODE ifcheck params 4 pname GL_OBJECT_PLANE,GL_EYE_PLANE
+
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 9d8c5a0..9fa2b74 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -58,7 +58,7 @@
         } else if (baseType.equals("void")) {
             // nothing.
         } else {
-            throw new RuntimeException("Uknown primitive basetype " + baseType);
+            throw new RuntimeException("Unknown primitive basetype " + baseType);
         }
         return jniName;
     }
@@ -200,15 +200,9 @@
                 if (emitExceptionCheck) {
                     out.println(iii + indent + "_exception = 1;");
                 }
-                out.println(iii + indent +
-                            (mUseCPlusPlus ? "_env" : "(*_env)") +
-                            "->ThrowNew(" +
-                            (mUseCPlusPlus ? "" : "_env, ") +
-                            "IAEClass, " +
-                            "\"" +
-                            (isBuffer ?
-                             "remaining()" : "length - " + offset) +
-                            " < needed\");");
+                out.println(iii + indent + "jniThrowException(_env, " +
+                        "\"java/lang/IllegalArgumentException\", " +
+                        "\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < needed\");");
                 out.println(iii + indent + "goto exit;");
                 needsExit = true;
                 out.println(iii + "}");
@@ -302,7 +296,7 @@
         }
         return false;
     }
-    
+
     String isRequiresFunc(CFunc cfunc) {
         String[] checks = mChecker.getChecks(cfunc.getName());
         int index = 1;
@@ -329,109 +323,94 @@
         }
         return null;
     }
-    
+
     void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
             boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
 
-                String[] checks = mChecker.getChecks(cfunc.getName());
+        String[] checks = mChecker.getChecks(cfunc.getName());
 
-                boolean lastWasIfcheck = false;
+        boolean lastWasIfcheck = false;
 
-                int index = 1;
-                if (checks != null) {
-                    while (index < checks.length) {
-                        if (checks[index].startsWith("check")) {
-                            if (lastWasIfcheck) {
-                                printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
-                                                      offset, remaining, iii);
-                            }
-                            lastWasIfcheck = false;
-                            if (cname != null && !cname.equals(checks[index + 1])) {
-                                index += 3;
-                                continue;
-                            }
-                            out.println(iii + "if (" + remaining + " < " +
-                                        checks[index + 2] +
-                                        ") {");
-                            if (emitExceptionCheck) {
-                                out.println(iii + indent + "_exception = 1;");
-                            }
-                    String exceptionClassName = "IAEClass";
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].startsWith("check")) {
+                    if (lastWasIfcheck) {
+                        printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
+                                offset, remaining, iii);
+                    }
+                    lastWasIfcheck = false;
+                    if (cname != null && !cname.equals(checks[index + 1])) {
+                        index += 3;
+                        continue;
+                    }
+                    out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
+                    if (emitExceptionCheck) {
+                        out.println(iii + indent + "_exception = 1;");
+                    }
+                    String exceptionClassName = "java/lang/IllegalArgumentException";
                     // If the "check" keyword was of the form
                     // "check_<class name>", use the class name in the
                     // exception to be thrown
                     int underscore = checks[index].indexOf('_');
                     if (underscore >= 0) {
-                    exceptionClassName = checks[index].substring(underscore + 1) + "Class";
-                    }
-                            out.println(iii + indent +
-                                        (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                        "->ThrowNew(" +
-                                        (mUseCPlusPlus ? "" : "_env, ") +
-                        exceptionClassName + ", " +
-                                        "\"" +
-                                        (isBuffer ?
-                                         "remaining()" : "length - " + offset) +
-                                        " < " + checks[index + 2] +
-                                        "\");");
-
-                            out.println(iii + indent + "goto exit;");
-                            needsExit = true;
-                            out.println(iii + "}");
-
-                            index += 3;
-                        } else if (checks[index].equals("ifcheck")) {
-                            String[] matches = checks[index + 4].split(",");
-
-                            if (!lastWasIfcheck) {
-                                out.println(iii + "int _needed;");
-                                out.println(iii +
-                                            "switch (" +
-                                            checks[index + 3] +
-                                            ") {");
-                            }
-
-                            for (int i = 0; i < matches.length; i++) {
-                                out.println("#if defined(" + matches[i] + ")");
-                                out.println(iii +
-                                            "    case " +
-                                            matches[i] +
-                                            ":");
-                                out.println("#endif // defined(" + matches[i] + ")");
-                            }
-                            out.println(iii +
-                                        "        _needed = " +
-                                        checks[index + 2] +
-                                        ";");
-                            out.println(iii +
-                                        "        break;");
-
-                            lastWasIfcheck = true;
-                            index += 5;
-                        } else if (checks[index].equals("return")) {
-                            // ignore
-                            index += 2;
-                        } else if (checks[index].equals("unsupported")) {
-                            // ignore
-                            index += 1;
-                        } else if (checks[index].equals("requires")) {
-                            // ignore
-                            index += 2;
-                        } else if (checks[index].equals("nullAllowed")) {
-                            // ignore
-                            index += 1;
+                        String abbr = checks[index].substring(underscore + 1);
+                        if (abbr.equals("AIOOBE")) {
+                            exceptionClassName = "java/lang/ArrayIndexOutOfBoundsException";
                         } else {
-                            System.out.println("Error: unknown keyword \"" +
-                                               checks[index] + "\"");
-                            System.exit(0);
+                            throw new RuntimeException("unknown exception abbreviation: " + abbr);
                         }
                     }
-                }
+                    out.println(iii + indent + "jniThrowException(_env, " +
+                            "\"" + exceptionClassName + "\", " +
+                            "\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < " + checks[index + 2] + "\");");
 
-                if (lastWasIfcheck) {
-                    printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
+                    out.println(iii + indent + "goto exit;");
+                    needsExit = true;
+                    out.println(iii + "}");
+
+                    index += 3;
+                } else if (checks[index].equals("ifcheck")) {
+                    String[] matches = checks[index + 4].split(",");
+
+                    if (!lastWasIfcheck) {
+                        out.println(iii + "int _needed;");
+                        out.println(iii + "switch (" + checks[index + 3] + ") {");
+                    }
+
+                    for (int i = 0; i < matches.length; i++) {
+                        out.println("#if defined(" + matches[i] + ")");
+                        out.println(iii + "    case " + matches[i] + ":");
+                        out.println("#endif // defined(" + matches[i] + ")");
+                    }
+                    out.println(iii + "        _needed = " + checks[index + 2] + ";");
+                    out.println(iii + "        break;");
+
+                    lastWasIfcheck = true;
+                    index += 5;
+                } else if (checks[index].equals("return")) {
+                    // ignore
+                    index += 2;
+                } else if (checks[index].equals("unsupported")) {
+                    // ignore
+                    index += 1;
+                } else if (checks[index].equals("requires")) {
+                    // ignore
+                    index += 2;
+                } else if (checks[index].equals("nullAllowed")) {
+                    // ignore
+                    index += 1;
+                } else {
+                    System.out.println("Error: unknown keyword \"" + checks[index] + "\"");
+                    System.exit(0);
                 }
             }
+        }
+
+        if (lastWasIfcheck) {
+            printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
+        }
+    }
 
     boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
         if (nonPrimitiveArgs.size() > 0) {
@@ -817,7 +796,7 @@
         boolean isUnsupported = isUnsupportedFunc(cfunc);
         if (isUnsupported) {
             out.println(indent +
-                        "_env->ThrowNew(UOEClass,");
+                        "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
             out.println(indent +
                         "    \"" + cfunc.getName() + "\");");
             if (!isVoid) {
@@ -828,13 +807,13 @@
             out.println();
             return;
         }
-        
+
         String requiresExtension = isRequiresFunc(cfunc);
         if (requiresExtension != null) {
             out.println(indent +
                         "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
             out.println(indent + indent +
-                        "_env->ThrowNew(UOEClass,");
+                        "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
             out.println(indent + indent +
                         "    \"" + cfunc.getName() + "\");");
             if (isVoid) {
@@ -945,7 +924,8 @@
                 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
                 String decl = type.getDeclaration();
                 out.println(indent + "if (!" + cname + ") {");
-                out.println(indent + "    _env->ThrowNew(IAEClass, \"" + cname + " == null\");");
+                out.println(indent + "    jniThrowException(_env, " +
+                        "\"java/lang/IllegalArgumentException\", \"" + cname + " == null\");");
                 out.println(indent + "    goto exit;");
                 needsExit = true;
                 out.println(indent + "}");
@@ -978,13 +958,9 @@
                     if (emitExceptionCheck) {
                         out.println(indent + indent + "_exception = 1;");
                     }
-                    out.println(indent + "    " +
-                                (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                "->ThrowNew(" +
-                                (mUseCPlusPlus ? "" : "_env, ") +
-                                "IAEClass, " +
-                                "\"" + cname +
-                                " == null\");");
+                    out.println(indent + "    jniThrowException(_env, " +
+                            "\"java/lang/IllegalArgumentException\", " +
+                            "\"" + cname + " == null\");");
                     out.println(indent + "    goto exit;");
                     needsExit = true;
                     out.println(indent + "}");
@@ -993,12 +969,8 @@
                     if (emitExceptionCheck) {
                         out.println(indent + indent + "_exception = 1;");
                     }
-                    out.println(indent + "    " +
-                                (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                "->ThrowNew(" +
-                                (mUseCPlusPlus ? "" : "_env, ") +
-                                "IAEClass, " +
-                                "\"" + offset + " < 0\");");
+                    out.println(indent + "    jniThrowException(_env, " +
+                            "\"java/lang/IllegalArgumentException\", \"" + offset + " < 0\");");
                     out.println(indent + "    goto exit;");
                     needsExit = true;
                     out.println(indent + "}");
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
index 294d1ce..5d418d7 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -27,10 +29,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -41,7 +39,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -63,26 +61,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -103,13 +81,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -122,4 +100,3 @@
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index e1c09f4..35a3c33 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -40,10 +42,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -54,7 +52,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -75,26 +73,6 @@
         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -115,13 +93,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -140,7 +118,8 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
@@ -153,4 +132,3 @@
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
index 2548b32..9b29a44 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -36,10 +38,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -50,7 +48,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -72,26 +70,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -112,13 +90,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -138,9 +116,9 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
index 4c297f7..823079f 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -34,10 +36,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -48,7 +46,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -70,26 +68,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -110,13 +88,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -136,10 +114,10 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
index e451e9a..13a2577 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -27,10 +29,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -41,7 +39,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -63,26 +61,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -103,13 +81,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -129,7 +107,8 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
@@ -147,4 +126,3 @@
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.cpp b/opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.cpp
index d92f515..ce6ab24 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.cpp
@@ -1,27 +1,19 @@
-#include <string.h>
+#include <stdlib.h>
 
 /* void glGetProgramInfoLog ( GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog ) */
-static
-jstring
-android_glGetProgramInfoLog (JNIEnv *_env, jobject _this, jint shader) {
+static jstring android_glGetProgramInfoLog(JNIEnv *_env, jobject, jint shader) {
     GLint infoLen = 0;
-    jstring _result = 0;
-    char* buf = 0;
     glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-    if (infoLen) {
-        char* buf = (char*) malloc(infoLen);
-        if (buf == 0) {
-            _env->ThrowNew(IAEClass, "out of memory");
-            goto exit;
-        }
-        glGetProgramInfoLog(shader, infoLen, NULL, buf);
-        _result = _env->NewStringUTF(buf);
-    } else {
-        _result = _env->NewStringUTF("");
+    if (!infoLen) {
+        return _env->NewStringUTF("");
     }
-exit:
-    if (buf) {
-            free(buf);
+    char* buf = (char*) malloc(infoLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
     }
-    return _result;
-}
\ No newline at end of file
+    glGetProgramInfoLog(shader, infoLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
+}
diff --git a/opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.cpp b/opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.cpp
index 5441d66..dd656b6 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.cpp
@@ -1,27 +1,19 @@
-#include <string.h>
+#include <stdlib.h>
 
 /* void glGetShaderInfoLog ( GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog ) */
-static
-jstring
-android_glGetShaderInfoLog (JNIEnv *_env, jobject _this, jint shader) {
+static jstring android_glGetShaderInfoLog(JNIEnv *_env, jobject, jint shader) {
     GLint infoLen = 0;
-    jstring _result = 0;
-    char* buf = 0;
     glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-    if (infoLen) {
-        char* buf = (char*) malloc(infoLen);
-        if (buf == 0) {
-            _env->ThrowNew(IAEClass, "out of memory");
-            goto exit;
-        }
-        glGetShaderInfoLog(shader, infoLen, NULL, buf);
-        _result = _env->NewStringUTF(buf);
-    } else {
-        _result = _env->NewStringUTF("");
+    if (!infoLen) {
+        return _env->NewStringUTF("");
     }
-exit:
-    if (buf) {
-            free(buf);
+    char* buf = (char*) malloc(infoLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
     }
-    return _result;
-}
\ No newline at end of file
+    glGetShaderInfoLog(shader, infoLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
+}
diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.cpp b/opengl/tools/glgen/stubs/gles11/glGetString.cpp
index a400859..239fe4a 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetString.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.cpp
@@ -1,11 +1,5 @@
-#include <string.h>

-

 /* const GLubyte * glGetString ( GLenum name ) */

-static

-jstring

-android_glGetString

-  (JNIEnv *_env, jobject _this, jint name) {

-    const char * chars = (const char *)glGetString((GLenum)name);

-    jstring output = _env->NewStringUTF(chars);

-    return output;

+static jstring android_glGetString(JNIEnv* _env, jobject, jint name) {

+    const char* chars = (const char*) glGetString((GLenum) name);

+    return _env->NewStringUTF(chars);

 }

diff --git a/opengl/tools/glgen/stubs/gles11/glShaderSource.cpp b/opengl/tools/glgen/stubs/gles11/glShaderSource.cpp
index c274108..125fd0f 100644
--- a/opengl/tools/glgen/stubs/gles11/glShaderSource.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glShaderSource.cpp
@@ -6,7 +6,7 @@
     (JNIEnv *_env, jobject _this, jint shader, jstring string) {
 
     if (!string) {
-        _env->ThrowNew(IAEClass, "string == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "string == null");
         return;
     }
 
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index c2464b0..f7315ee 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2006, 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 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -63,10 +65,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jclass G11ImplClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
@@ -84,7 +82,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -114,26 +112,6 @@
         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -154,7 +132,7 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     if (*array == NULL) {
@@ -163,7 +141,7 @@
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -207,7 +185,8 @@
                 releasePointer(_env, array, buf, 0);
             }
         } else {
-            _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+            jniThrowException(_env, "java/lang/IllegalArgumentException",
+                              "Must use a native order direct Buffer");
         }
     }
     return buf;
@@ -250,7 +229,7 @@
         }
     }
 }
-    
+
 static bool
 checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
     for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
@@ -279,4 +258,3 @@
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
index 3727106..cd730aa 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -18,7 +18,7 @@
 
 package com.google.android.gles_jni;
 
-import android.app.ActivityThread;
+import android.app.AppGlobals;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.os.Build;
@@ -64,7 +64,7 @@
     private static boolean allowIndirectBuffers(String appName) {
         boolean result = false;
         int version = 0;
-        IPackageManager pm = ActivityThread.getPackageManager();
+        IPackageManager pm = AppGlobals.getPackageManager();
         try {
             ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
             if (applicationInfo != null) {
diff --git a/opengl/tools/glgen/stubs/jsr239/glGetString.cpp b/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
index a400859..cd6e3f3 100644
--- a/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
@@ -1,11 +1,5 @@
-#include <string.h>

-

 /* const GLubyte * glGetString ( GLenum name ) */

-static

-jstring

-android_glGetString

-  (JNIEnv *_env, jobject _this, jint name) {

-    const char * chars = (const char *)glGetString((GLenum)name);

-    jstring output = _env->NewStringUTF(chars);

-    return output;

+static jstring android_glGetString(JNIEnv *_env, jobject, jint name) {

+    const char* chars = (const char*) glGetString((GLenum) name);

+    return _env->NewStringUTF(chars);

 }

diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 8a00a2e..9daaad8 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -41,7 +41,7 @@
 	libGLESv1_CM \
 	libbinder \
 	libui \
-	libsurfaceflinger_client
+	libgui
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, corecg graphics)
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 64cff96..a774841 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -93,7 +93,11 @@
 int DisplayHardware::getHeight() const          { return mHeight; }
 PixelFormat DisplayHardware::getFormat() const  { return mFormat; }
 uint32_t DisplayHardware::getMaxTextureSize() const { return mMaxTextureSize; }
-uint32_t DisplayHardware::getMaxViewportDims() const { return mMaxViewportDims; }
+
+uint32_t DisplayHardware::getMaxViewportDims() const {
+    return mMaxViewportDims[0] < mMaxViewportDims[1] ?
+            mMaxViewportDims[0] : mMaxViewportDims[1];
+}
 
 void DisplayHardware::init(uint32_t dpy)
 {
@@ -228,7 +232,7 @@
             eglQueryString(display, EGL_EXTENSIONS));
 
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
-    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims);
+    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
 
 
 #ifdef EGL_ANDROID_swap_rectangle
@@ -260,7 +264,7 @@
     LOGI("version   : %s", extensions.getVersion());
     LOGI("extensions: %s", extensions.getExtension());
     LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
-    LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
+    LOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]);
     LOGI("flags = %08x", mFlags);
 
     // Unbind the context from this thread
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index ee7a2af..cdf89fd 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -108,7 +108,7 @@
     PixelFormat     mFormat;
     uint32_t        mFlags;
     mutable uint32_t mPageFlipCount;
-    GLint           mMaxViewportDims;
+    GLint           mMaxViewportDims[2];
     GLint           mMaxTextureSize;
     
     HWComposer*     mHwc;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index 90865da..59b7e5a 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -38,23 +38,10 @@
 #include "SurfaceFlinger.h"
 
 // ----------------------------------------------------------------------------
-// the sim build doesn't have gettid
-
-#ifndef HAVE_GETTID
-# define gettid getpid
-#endif
-
-// ----------------------------------------------------------------------------
 namespace android {
 
-static char const * kSleepFileName = "/sys/power/wait_for_fb_sleep";
-static char const * kWakeFileName = "/sys/power/wait_for_fb_wake";
-static char const * const kOldSleepFileName = "/sys/android_power/wait_for_fb_sleep";
-static char const * const kOldWakeFileName = "/sys/android_power/wait_for_fb_wake";
-
-// This dir exists if the framebuffer console is present, either built into
-// the kernel or loaded as a module.
-static char const * const kFbconSysDir = "/sys/class/graphics/fbcon";
+static char const * const kSleepFileName = "/sys/power/wait_for_fb_sleep";
+static char const * const kWakeFileName  = "/sys/power/wait_for_fb_wake";
 
 // ----------------------------------------------------------------------------
 
@@ -122,237 +109,13 @@
 
 status_t DisplayHardwareBase::DisplayEventThread::readyToRun()
 {
-    if (access(kSleepFileName, R_OK) || access(kWakeFileName, R_OK)) {
-        if (access(kOldSleepFileName, R_OK) || access(kOldWakeFileName, R_OK)) {
-            LOGE("Couldn't open %s or %s", kSleepFileName, kWakeFileName);
-            return NO_INIT;
-        }
-        kSleepFileName = kOldSleepFileName;
-        kWakeFileName = kOldWakeFileName;
-    }
     return NO_ERROR;
 }
 
 status_t DisplayHardwareBase::DisplayEventThread::initCheck() const
 {
-    return (((access(kSleepFileName, R_OK) == 0 &&
-            access(kWakeFileName, R_OK) == 0) ||
-            (access(kOldSleepFileName, R_OK) == 0 &&
-            access(kOldWakeFileName, R_OK) == 0)) &&
-            access(kFbconSysDir, F_OK) != 0) ? NO_ERROR : NO_INIT;
-}
-
-// ----------------------------------------------------------------------------
-
-pid_t DisplayHardwareBase::ConsoleManagerThread::sSignalCatcherPid = 0;
-
-DisplayHardwareBase::ConsoleManagerThread::ConsoleManagerThread(
-        const sp<SurfaceFlinger>& flinger)
-    : DisplayEventThreadBase(flinger), consoleFd(-1)
-{   
-    sSignalCatcherPid = 0;
-
-    // create a new console
-    char const * const ttydev = "/dev/tty0";
-    int fd = open(ttydev, O_RDWR | O_SYNC);
-    if (fd<0) {
-        LOGE("Can't open %s", ttydev);
-        this->consoleFd = -errno;
-        return;
-    }
-
-    // to make sure that we are in text mode
-    int res = ioctl(fd, KDSETMODE, (void*) KD_TEXT);
-    if (res<0) {
-        LOGE("ioctl(%d, KDSETMODE, ...) failed, res %d (%s)",
-                fd, res, strerror(errno));
-    }
-    
-    // get the current console
-    struct vt_stat vs;
-    res = ioctl(fd, VT_GETSTATE, &vs);
-    if (res<0) {
-        LOGE("ioctl(%d, VT_GETSTATE, ...) failed, res %d (%s)",
-                fd, res, strerror(errno));
-        this->consoleFd = -errno;
-        return;
-    }
-
-    // switch to console 7 (which is what X normaly uses)
-    int vtnum = 7;
-    do {
-        res = ioctl(fd, VT_ACTIVATE, (void*)vtnum);
-    } while(res < 0 && errno == EINTR);
-    if (res<0) {
-        LOGE("ioctl(%d, VT_ACTIVATE, ...) failed, %d (%s) for %d",
-                fd, errno, strerror(errno), vtnum);
-        this->consoleFd = -errno;
-        return;
-    }
-
-    do {
-        res = ioctl(fd, VT_WAITACTIVE, (void*)vtnum);
-    } while(res < 0 && errno == EINTR);
-    if (res<0) {
-        LOGE("ioctl(%d, VT_WAITACTIVE, ...) failed, %d %d %s for %d",
-                fd, res, errno, strerror(errno), vtnum);
-        this->consoleFd = -errno;
-        return;
-    }
-
-    // open the new console
-    close(fd);
-    fd = open(ttydev, O_RDWR | O_SYNC);
-    if (fd<0) {
-        LOGE("Can't open new console %s", ttydev);
-        this->consoleFd = -errno;
-        return;
-    }
-
-    /* disable console line buffer, echo, ... */
-    struct termios ttyarg;
-    ioctl(fd, TCGETS , &ttyarg);
-    ttyarg.c_iflag = 0;
-    ttyarg.c_lflag = 0;
-    ioctl(fd, TCSETS , &ttyarg);
-
-    // set up signals so we're notified when the console changes
-    // we can't use SIGUSR1 because it's used by the java-vm
-    vm.mode = VT_PROCESS;
-    vm.waitv = 0;
-    vm.relsig = SIGUSR2;
-    vm.acqsig = SIGUNUSED;
-    vm.frsig = 0;
-
-    struct sigaction act;
-    sigemptyset(&act.sa_mask);
-    act.sa_handler = sigHandler;
-    act.sa_flags = 0;
-    sigaction(vm.relsig, &act, NULL);
-
-    sigemptyset(&act.sa_mask);
-    act.sa_handler = sigHandler;
-    act.sa_flags = 0;
-    sigaction(vm.acqsig, &act, NULL);
-
-    sigset_t mask;
-    sigemptyset(&mask);
-    sigaddset(&mask, vm.relsig);
-    sigaddset(&mask, vm.acqsig);
-    sigprocmask(SIG_BLOCK, &mask, NULL);
-
-    // switch to graphic mode
-    res = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS);
-    LOGW_IF(res<0,
-            "ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, res %d", fd, res);
-
-    this->prev_vt_num = vs.v_active;
-    this->vt_num = vtnum;
-    this->consoleFd = fd;
-}
-
-DisplayHardwareBase::ConsoleManagerThread::~ConsoleManagerThread()
-{   
-    if (this->consoleFd >= 0) {
-        int fd = this->consoleFd;
-        int prev_vt_num = this->prev_vt_num;
-        int res;
-        ioctl(fd, KDSETMODE, (void*)KD_TEXT);
-        do {
-            res = ioctl(fd, VT_ACTIVATE, (void*)prev_vt_num);
-        } while(res < 0 && errno == EINTR);
-        do {
-            res = ioctl(fd, VT_WAITACTIVE, (void*)prev_vt_num);
-        } while(res < 0 && errno == EINTR);
-        close(fd);    
-        char const * const ttydev = "/dev/tty0";
-        fd = open(ttydev, O_RDWR | O_SYNC);
-        ioctl(fd, VT_DISALLOCATE, 0);
-        close(fd);
-    }
-}
-
-status_t DisplayHardwareBase::ConsoleManagerThread::readyToRun()
-{
-    if (this->consoleFd >= 0) {
-        sSignalCatcherPid = gettid();
-        
-        sigset_t mask;
-        sigemptyset(&mask);
-        sigaddset(&mask, vm.relsig);
-        sigaddset(&mask, vm.acqsig);
-        sigprocmask(SIG_BLOCK, &mask, NULL);
-
-        int res = ioctl(this->consoleFd, VT_SETMODE, &vm);
-        if (res<0) {
-            LOGE("ioctl(%d, VT_SETMODE, ...) failed, %d (%s)",
-                    this->consoleFd, errno, strerror(errno));
-        }
-        return NO_ERROR;
-    }
-    return this->consoleFd;
-}
-
-void DisplayHardwareBase::ConsoleManagerThread::requestExit()
-{
-    Thread::requestExit();
-    if (sSignalCatcherPid != 0) {
-        // wake the thread up
-        kill(sSignalCatcherPid, SIGINT);
-        // wait for it...
-    }
-}
-
-void DisplayHardwareBase::ConsoleManagerThread::sigHandler(int sig)
-{
-    // resend the signal to our signal catcher thread
-    LOGW("received signal %d in thread %d, resending to %d",
-            sig, gettid(), sSignalCatcherPid);
-
-    // we absolutely need the delays below because without them
-    // our main thread never gets a chance to handle the signal.
-    usleep(10000);
-    kill(sSignalCatcherPid, sig);
-    usleep(10000);
-}
-
-status_t DisplayHardwareBase::ConsoleManagerThread::releaseScreen() const
-{
-    int fd = this->consoleFd;
-    int err = ioctl(fd, VT_RELDISP, (void*)1);
-    LOGE_IF(err<0, "ioctl(%d, VT_RELDISP, 1) failed %d (%s)",
-        fd, errno, strerror(errno));
-    return (err<0) ? (-errno) : status_t(NO_ERROR);
-}
-
-bool DisplayHardwareBase::ConsoleManagerThread::threadLoop()
-{
-    sigset_t mask;
-    sigemptyset(&mask);
-    sigaddset(&mask, vm.relsig);
-    sigaddset(&mask, vm.acqsig);
-
-    int sig = 0;
-    sigwait(&mask, &sig);
-
-    if (sig == vm.relsig) {
-        sp<SurfaceFlinger> flinger = mFlinger.promote();
-        //LOGD("About to give-up screen, flinger = %p", flinger.get());
-        if (flinger != 0)
-            flinger->screenReleased(0);
-    } else if (sig == vm.acqsig) {
-        sp<SurfaceFlinger> flinger = mFlinger.promote();
-        //LOGD("Screen about to return, flinger = %p", flinger.get());
-        if (flinger != 0) 
-            flinger->screenAcquired(0);
-    }
-    
-    return true;
-}
-
-status_t DisplayHardwareBase::ConsoleManagerThread::initCheck() const
-{
-    return consoleFd >= 0 ? NO_ERROR : NO_INIT;
+    return ((access(kSleepFileName, R_OK) == 0 &&
+            access(kWakeFileName, R_OK) == 0)) ? NO_ERROR : NO_INIT;
 }
 
 // ----------------------------------------------------------------------------
@@ -362,10 +125,6 @@
     : mCanDraw(true), mScreenAcquired(true)
 {
     mDisplayEventThread = new DisplayEventThread(flinger);
-    if (mDisplayEventThread->initCheck() != NO_ERROR) {
-        // fall-back on the console
-        mDisplayEventThread = new ConsoleManagerThread(flinger);
-    }
 }
 
 DisplayHardwareBase::~DisplayHardwareBase()
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index fa6a0c4..30eb258 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -73,24 +73,6 @@
         virtual status_t initCheck() const;
     };
 
-    class ConsoleManagerThread : public DisplayEventThreadBase 
-    {
-        int consoleFd;
-        int vt_num;
-        int prev_vt_num;
-        vt_mode vm;
-        static void sigHandler(int sig);
-        static pid_t sSignalCatcherPid;
-    public:
-                ConsoleManagerThread(const sp<SurfaceFlinger>& flinger);
-        virtual ~ConsoleManagerThread();
-        virtual bool threadLoop();
-        virtual status_t readyToRun();
-        virtual void requestExit();
-        virtual status_t releaseScreen() const;
-        virtual status_t initCheck() const;
-    };
-
     sp<DisplayEventThreadBase>  mDisplayEventThread;
     mutable int                 mCanDraw;
     mutable int                 mScreenAcquired;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 99d904d..8df2b92 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -52,6 +52,7 @@
 Layer::Layer(SurfaceFlinger* flinger,
         DisplayID display, const sp<Client>& client)
     :   LayerBaseClient(flinger, display, client),
+        mFormat(PIXEL_FORMAT_NONE),
         mGLExtensions(GLExtensions::getInstance()),
         mNeedsBlending(true),
         mNeedsDithering(false),
@@ -59,7 +60,8 @@
         mProtectedByApp(false),
         mTextureManager(),
         mBufferManager(mTextureManager),
-        mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false)
+        mWidth(0), mHeight(0),
+        mNeedsScaling(false), mFixedSize(false)
 {
 }
 
@@ -77,6 +79,10 @@
     }
 }
 
+void Layer::destroy() const {
+    mFlinger->destroyLayer(this);
+}
+
 status_t Layer::setToken(const sp<UserClient>& userClient,
         SharedClient* sharedClient, int32_t token)
 {
@@ -145,18 +151,6 @@
     return sur;
 }
 
-status_t Layer::ditch()
-{
-    // NOTE: Called from the main UI thread
-
-    // the layer is not on screen anymore. free as much resources as possible
-    mFreezeLock.clear();
-
-    Mutex::Autolock _l(mLock);
-    mWidth = mHeight = 0;
-    return NO_ERROR;
-}
-
 status_t Layer::setBuffers( uint32_t w, uint32_t h,
                             PixelFormat format, uint32_t flags)
 {
@@ -661,8 +655,9 @@
 
         // update the layer size and release freeze-lock
         const Layer::State& front(drawingState());
-        if (newFrontBuffer->getWidth()  == front.requested_w &&
-            newFrontBuffer->getHeight() == front.requested_h)
+        if ((newFrontBuffer->getWidth()  == front.requested_w &&
+            newFrontBuffer->getHeight() == front.requested_h) ||
+            isFixedSize())
         {
             if ((front.w != front.requested_w) ||
                 (front.h != front.requested_h))
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 128f93d..278d64e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -82,7 +82,6 @@
     virtual bool isSecure() const           { return mSecure; }
     virtual bool isProtected() const;
     virtual sp<Surface> createSurface() const;
-    virtual status_t ditch();
     virtual void onRemoved();
 
     // only for debugging
@@ -93,6 +92,7 @@
         return mFreezeLock; }
 
 protected:
+    virtual void destroy() const;
     virtual void dump(String8& result, char* scratch, size_t size) const;
 
 private:
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 6025ed4..022f251 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -616,10 +616,7 @@
      */
 
     // destroy client resources
-    sp<LayerBaseClient> layer = getOwner();
-    if (layer != 0) {
-        mFlinger->destroySurface(layer);
-    }
+    mFlinger->destroySurface(mOwner);
 }
 
 sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 7162e47..6c49a19 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -202,10 +202,6 @@
      */
     virtual bool isProtected() const   { return false; }
 
-    /** Called from the main thread, when the surface is removed from the
-     * draw list */
-    virtual status_t ditch() { return NO_ERROR; }
-
     /** called with the state lock when the surface is removed from the
      *  current list */
     virtual void onRemoved() { };
@@ -271,7 +267,8 @@
     volatile    int32_t         mInvalidate;
                 
 
-protected:
+public:
+    // called from class SurfaceFlinger
     virtual ~LayerBase();
 
 private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a9fa1ef..b7a51a4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -387,6 +387,9 @@
 {
     waitForEvent();
 
+    // call Layer's destructor
+    handleDestroyLayers();
+
     // check for transactions
     if (UNLIKELY(mConsoleSignals)) {
         handleConsoleEvents();
@@ -395,7 +398,7 @@
     if (LIKELY(mTransactionCount == 0)) {
         // if we're in a global transaction, don't do anything.
         const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
-        uint32_t transactionFlags = getTransactionFlags(mask);
+        uint32_t transactionFlags = peekTransactionFlags(mask);
         if (LIKELY(transactionFlags)) {
             handleTransaction(transactionFlags);
         }
@@ -480,39 +483,27 @@
 
 void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
 {
-    Vector< sp<LayerBase> > ditchedLayers;
+    Mutex::Autolock _l(mStateLock);
+    const nsecs_t now = systemTime();
+    mDebugInTransaction = now;
 
-    /*
-     * Perform and commit the transaction
-     */
+    // Here we're guaranteed that some transaction flags are set
+    // so we can call handleTransactionLocked() unconditionally.
+    // We call getTransactionFlags(), which will also clear the flags,
+    // with mStateLock held to guarantee that mCurrentState won't change
+    // until the transaction is committed.
 
-    { // scope for the lock
-        Mutex::Autolock _l(mStateLock);
-        const nsecs_t now = systemTime();
-        mDebugInTransaction = now;
-        handleTransactionLocked(transactionFlags, ditchedLayers);
-        mLastTransactionTime = systemTime() - now;
-        mDebugInTransaction = 0;
-        invalidateHwcGeometry();
-        // here the transaction has been committed
-    }
+    const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+    transactionFlags = getTransactionFlags(mask);
+    handleTransactionLocked(transactionFlags);
 
-    /*
-     * Clean-up all layers that went away
-     * (do this without the lock held)
-     */
-
-    const size_t count = ditchedLayers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        if (ditchedLayers[i] != 0) {
-            //LOGD("ditching layer %p", ditchedLayers[i].get());
-            ditchedLayers[i]->ditch();
-        }
-    }
+    mLastTransactionTime = systemTime() - now;
+    mDebugInTransaction = 0;
+    invalidateHwcGeometry();
+    // here the transaction has been committed
 }
 
-void SurfaceFlinger::handleTransactionLocked(
-        uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers)
+void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
 {
     const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
     const size_t count = currentLayers.size();
@@ -584,7 +575,6 @@
                 const sp<LayerBase>& layer(previousLayers[i]);
                 if (currentLayers.indexOf( layer ) < 0) {
                     // this layer is not visible anymore
-                    ditchedLayers.add(layer);
                     mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
                 }
             }
@@ -594,13 +584,38 @@
     commitTransaction();
 }
 
+void SurfaceFlinger::destroyLayer(LayerBase const* layer)
+{
+    Mutex::Autolock _l(mDestroyedLayerLock);
+    mDestroyedLayers.add(layer);
+    signalEvent();
+}
+
+void SurfaceFlinger::handleDestroyLayers()
+{
+    Vector<LayerBase const *> destroyedLayers;
+
+    { // scope for the lock
+        Mutex::Autolock _l(mDestroyedLayerLock);
+        destroyedLayers = mDestroyedLayers;
+        mDestroyedLayers.clear();
+    }
+
+    // call destructors without a lock held
+    const size_t count = destroyedLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        //LOGD("destroying %s", destroyedLayers[i]->getName().string());
+        delete destroyedLayers[i];
+    }
+}
+
 sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
 {
     return new FreezeLock(const_cast<SurfaceFlinger *>(this));
 }
 
 void SurfaceFlinger::computeVisibleRegions(
-    LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
+    const LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
 {
     const GraphicPlane& plane(graphicPlane(0));
     const Transform& planeTransform(plane.transform());
@@ -735,8 +750,7 @@
 void SurfaceFlinger::handlePageFlip()
 {
     bool visibleRegions = mVisibleRegionsDirty;
-    LayerVector& currentLayers(
-            const_cast<LayerVector&>(mDrawingState.layersSortedByZ));
+    const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
     visibleRegions |= lockPageFlip(currentLayers);
 
         const DisplayHardware& hw = graphicPlane(0).displayHardware();
@@ -748,9 +762,8 @@
             /*
              *  rebuild the visible layer list
              */
+            const size_t count = currentLayers.size();
             mVisibleLayersSortedByZ.clear();
-            const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
-            size_t count = currentLayers.size();
             mVisibleLayersSortedByZ.setCapacity(count);
             for (size_t i=0 ; i<count ; i++) {
                 if (!currentLayers[i]->visibleRegionScreen.isEmpty())
@@ -1096,15 +1109,15 @@
 ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
         const sp<LayerBaseClient>& lbc)
 {
-    Mutex::Autolock _l(mStateLock);
-
     // attach this layer to the client
-    ssize_t name = client->attachLayer(lbc);
+    size_t name = client->attachLayer(lbc);
+
+    Mutex::Autolock _l(mStateLock);
 
     // add this layer to the current state list
     addLayer_l(lbc);
 
-    return name;
+    return ssize_t(name);
 }
 
 status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
@@ -1155,6 +1168,11 @@
     return NO_ERROR;
 }
 
+uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
+{
+    return android_atomic_release_load(&mTransactionFlags);
+}
+
 uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
 {
     return android_atomic_and(~flags, &mTransactionFlags) & flags;
@@ -1243,8 +1261,10 @@
     return orientation;
 }
 
-sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid,
-        const String8& name, ISurfaceComposerClient::surface_data_t* params,
+sp<ISurface> SurfaceFlinger::createSurface(
+        ISurfaceComposerClient::surface_data_t* params,
+        const String8& name,
+        const sp<Client>& client,
         DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
         uint32_t flags)
 {
@@ -1362,51 +1382,26 @@
     return err;
 }
 
-status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
+status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer)
 {
     // called by ~ISurface() when all references are gone
-
-    class MessageDestroySurface : public MessageBase {
-        SurfaceFlinger* flinger;
-        sp<LayerBaseClient> layer;
-    public:
-        MessageDestroySurface(
-                SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer)
-            : flinger(flinger), layer(layer) { }
-        virtual bool handler() {
-            sp<LayerBaseClient> l(layer);
-            layer.clear(); // clear it outside of the lock;
-            Mutex::Autolock _l(flinger->mStateLock);
-            /*
-             * remove the layer from the current list -- chances are that it's
-             * not in the list anyway, because it should have been removed
-             * already upon request of the client (eg: window manager).
-             * However, a buggy client could have not done that.
-             * Since we know we don't have any more clients, we don't need
-             * to use the purgatory.
-             */
-            status_t err = flinger->removeLayer_l(l);
-            if (err == NAME_NOT_FOUND) {
-                // The surface wasn't in the current list, which means it was
-                // removed already, which means it is in the purgatory,
-                // and need to be removed from there.
-                // This needs to happen from the main thread since its dtor
-                // must run from there (b/c of OpenGL ES). Additionally, we
-                // can't really acquire our internal lock from
-                // destroySurface() -- see postMessage() below.
-                ssize_t idx = flinger->mLayerPurgatory.remove(l);
-                LOGE_IF(idx < 0,
-                        "layer=%p is not in the purgatory list", l.get());
-            }
-
-            LOGE_IF(err<0 && err != NAME_NOT_FOUND,
-                    "error removing layer=%p (%s)", l.get(), strerror(-err));
-            return true;
+    status_t err = NO_ERROR;
+    sp<LayerBaseClient> l(layer.promote());
+    if (l != NULL) {
+        Mutex::Autolock _l(mStateLock);
+        err = removeLayer_l(l);
+        if (err == NAME_NOT_FOUND) {
+            // The surface wasn't in the current list, which means it was
+            // removed already, which means it is in the purgatory,
+            // and need to be removed from there.
+            ssize_t idx = mLayerPurgatory.remove(l);
+            LOGE_IF(idx < 0,
+                    "layer=%p is not in the purgatory list", l.get());
         }
-    };
-
-    postMessageAsync( new MessageDestroySurface(this, layer) );
-    return NO_ERROR;
+        LOGE_IF(err<0 && err != NAME_NOT_FOUND,
+                "error removing layer=%p (%s)", l.get(), strerror(-err));
+    }
+    return err;
 }
 
 status_t SurfaceFlinger::setClientState(
@@ -2381,15 +2376,17 @@
     return NO_ERROR;
 }
 
-ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer)
+size_t Client::attachLayer(const sp<LayerBaseClient>& layer)
 {
-    int32_t name = android_atomic_inc(&mNameGenerator);
+    Mutex::Autolock _l(mLock);
+    size_t name = mNameGenerator++;
     mLayers.add(name, layer);
     return name;
 }
 
 void Client::detachLayer(const LayerBaseClient* layer)
 {
+    Mutex::Autolock _l(mLock);
     // we do a linear search here, because this doesn't happen often
     const size_t count = mLayers.size();
     for (size_t i=0 ; i<count ; i++) {
@@ -2399,9 +2396,11 @@
         }
     }
 }
-sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
+sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
+{
+    Mutex::Autolock _l(mLock);
     sp<LayerBaseClient> lbc;
-    const wp<LayerBaseClient>& layer(mLayers.valueFor(i));
+    wp<LayerBaseClient> layer(mLayers.valueFor(i));
     if (layer != 0) {
         lbc = layer.promote();
         LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i));
@@ -2416,12 +2415,12 @@
     return -1;
 }
 sp<ISurface> Client::createSurface(
-        ISurfaceComposerClient::surface_data_t* params, int pid,
+        ISurfaceComposerClient::surface_data_t* params,
         const String8& name,
         DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
         uint32_t flags)
 {
-    return mFlinger->createSurface(this, pid, name, params,
+    return mFlinger->createSurface(params, name, this,
             display, w, h, format, flags);
 }
 status_t Client::destroySurface(SurfaceID sid) {
@@ -2515,7 +2514,7 @@
             }
             break;
         }
-        if (++name >= SharedBufferStack::NUM_LAYERS_MAX)
+        if (++name >= int32_t(SharedBufferStack::NUM_LAYERS_MAX))
             name = NO_MEMORY;
     } while(name >= 0);
 
@@ -2525,7 +2524,7 @@
 }
 
 sp<ISurface> UserClient::createSurface(
-        ISurfaceComposerClient::surface_data_t* params, int pid,
+        ISurfaceComposerClient::surface_data_t* params,
         const String8& name,
         DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
         uint32_t flags) {
@@ -2555,22 +2554,9 @@
         LOGE("createGraphicBuffer: unable to create GraphicBuffer");
         return 0;
     }
-    Mutex::Autolock _l(mLock);
-    mBuffers.add(graphicBuffer);
     return graphicBuffer;
 }
 
-void GraphicBufferAlloc::freeAllGraphicBuffersExcept(int bufIdx) {
-    Mutex::Autolock _l(mLock);
-    if (0 <= bufIdx && bufIdx < mBuffers.size()) {
-        sp<GraphicBuffer> b(mBuffers[bufIdx]);
-        mBuffers.clear();
-        mBuffers.add(b);
-    } else {
-        mBuffers.clear();
-    }
-}
-
 // ---------------------------------------------------------------------------
 
 GraphicPlane::GraphicPlane()
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9566819..992861a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -65,7 +65,7 @@
     status_t initCheck() const;
 
     // protected by SurfaceFlinger::mStateLock
-    ssize_t attachLayer(const sp<LayerBaseClient>& layer);
+    size_t attachLayer(const sp<LayerBaseClient>& layer);
     void detachLayer(const LayerBaseClient* layer);
     sp<LayerBaseClient> getLayerUser(int32_t i) const;
 
@@ -75,15 +75,21 @@
     virtual sp<IMemoryHeap> getControlBlock() const;
     virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
     virtual sp<ISurface> createSurface(
-            surface_data_t* params, int pid, const String8& name,
+            surface_data_t* params, const String8& name,
             DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
             uint32_t flags);
     virtual status_t destroySurface(SurfaceID surfaceId);
     virtual status_t setState(int32_t count, const layer_state_t* states);
 
-    DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
+    // constant
     sp<SurfaceFlinger> mFlinger;
-    int32_t mNameGenerator;
+
+    // protected by mLock
+    DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
+    size_t mNameGenerator;
+
+    // thread-safe
+    mutable Mutex mLock;
 };
 
 class UserClient : public BnSurfaceComposerClient
@@ -107,7 +113,7 @@
     virtual sp<IMemoryHeap> getControlBlock() const;
     virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
     virtual sp<ISurface> createSurface(
-            surface_data_t* params, int pid, const String8& name,
+            surface_data_t* params, const String8& name,
             DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
             uint32_t flags);
     virtual status_t destroySurface(SurfaceID surfaceId);
@@ -125,14 +131,8 @@
 public:
     GraphicBufferAlloc();
     virtual ~GraphicBufferAlloc();
-
     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
         PixelFormat format, uint32_t usage);
-    virtual void freeAllGraphicBuffersExcept(int bufIdx);
-
-private:
-    Vector<sp<GraphicBuffer> > mBuffers;
-    Mutex mLock;
 };
 
 // ---------------------------------------------------------------------------
@@ -227,6 +227,7 @@
     status_t addLayer(const sp<LayerBase>& layer);
     status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
     void invalidateHwcGeometry();
+    void destroyLayer(LayerBase const* layer);
 
     sp<Layer> getLayer(const sp<ISurface>& sur) const;
 
@@ -238,9 +239,10 @@
     friend class Layer;
     friend class LayerDim;
 
-    sp<ISurface> createSurface(const sp<Client>& client,
-            int pid, const String8& name,
+    sp<ISurface> createSurface(
             ISurfaceComposerClient::surface_data_t* params,
+            const String8& name,
+            const sp<Client>& client,
             DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
             uint32_t flags);
 
@@ -254,7 +256,7 @@
             uint32_t w, uint32_t h, uint32_t flags);
 
     status_t removeSurface(const sp<Client>& client, SurfaceID sid);
-    status_t destroySurface(const sp<LayerBaseClient>& layer);
+    status_t destroySurface(const wp<LayerBaseClient>& layer);
     status_t setClientState(const sp<Client>& client,
             int32_t count, const layer_state_t* states);
 
@@ -299,12 +301,11 @@
 private:
             void        handleConsoleEvents();
             void        handleTransaction(uint32_t transactionFlags);
-            void        handleTransactionLocked(
-                            uint32_t transactionFlags, 
-                            Vector< sp<LayerBase> >& ditchedLayers);
+            void        handleTransactionLocked(uint32_t transactionFlags);
+            void        handleDestroyLayers();
 
             void        computeVisibleRegions(
-                            LayerVector& currentLayers,
+                            const LayerVector& currentLayers,
                             Region& dirtyRegion,
                             Region& wormholeRegion);
 
@@ -324,6 +325,7 @@
             status_t    purgatorizeLayer_l(const sp<LayerBase>& layer);
 
             uint32_t    getTransactionFlags(uint32_t flags);
+            uint32_t    peekTransactionFlags(uint32_t flags);
             uint32_t    setTransactionFlags(uint32_t flags);
             void        commitTransaction();
 
@@ -371,7 +373,6 @@
                 // access must be protected by mStateLock
     mutable     Mutex                   mStateLock;
                 State                   mCurrentState;
-                State                   mDrawingState;
     volatile    int32_t                 mTransactionFlags;
     volatile    int32_t                 mTransactionCount;
                 Condition               mTransactionCV;
@@ -395,6 +396,7 @@
                 
                 // Can only accessed from the main thread, these members
                 // don't need synchronization
+                State                       mDrawingState;
                 Region                      mDirtyRegion;
                 Region                      mDirtyRegionRemovedLayer;
                 Region                      mInvalidRegion;
@@ -422,6 +424,11 @@
                 // these are thread safe
     mutable     Barrier                     mReadyToRunBarrier;
 
+
+                // protected by mDestroyedLayerLock;
+    mutable     Mutex                       mDestroyedLayerLock;
+                Vector<LayerBase const *>   mDestroyedLayers;
+
                 // atomic variables
                 enum {
                     eConsoleReleased = 1,
diff --git a/services/surfaceflinger/TextureManager.cpp b/services/surfaceflinger/TextureManager.cpp
index 9e24f90..bb63c37 100644
--- a/services/surfaceflinger/TextureManager.cpp
+++ b/services/surfaceflinger/TextureManager.cpp
@@ -144,7 +144,7 @@
     }
 
     // construct an EGL_NATIVE_BUFFER_ANDROID
-    android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+    ANativeWindowBuffer* clientBuf = buffer->getNativeBuffer();
 
     // create the new EGLImageKHR
     const EGLint attrs[] = {
diff --git a/services/surfaceflinger/tests/resize/Android.mk b/services/surfaceflinger/tests/resize/Android.mk
index 24c2d01..d81679e 100644
--- a/services/surfaceflinger/tests/resize/Android.mk
+++ b/services/surfaceflinger/tests/resize/Android.mk
@@ -8,7 +8,7 @@
 	libcutils \
 	libutils \
     libui \
-    libsurfaceflinger_client
+    libgui
 
 LOCAL_MODULE:= test-resize
 
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index 0ccca77..18c54b3 100644
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp
@@ -29,13 +29,6 @@
 using namespace android;
 
 namespace android {
-class Test {
-public:
-    static const sp<ISurface>& getISurface(const sp<Surface>& s) {
-        return s->getISurface();
-    }
-};
-};
 
 int main(int argc, char** argv)
 {
diff --git a/services/surfaceflinger/tests/screencap/Android.mk b/services/surfaceflinger/tests/screencap/Android.mk
index 1cfb471..5cdd1a8 100644
--- a/services/surfaceflinger/tests/screencap/Android.mk
+++ b/services/surfaceflinger/tests/screencap/Android.mk
@@ -10,7 +10,7 @@
 	libbinder \
 	libskia \
     libui \
-    libsurfaceflinger_client
+    libgui
 
 LOCAL_MODULE:= test-screencap
 
diff --git a/services/surfaceflinger/tests/surface/Android.mk b/services/surfaceflinger/tests/surface/Android.mk
index ce0e807..c59060e 100644
--- a/services/surfaceflinger/tests/surface/Android.mk
+++ b/services/surfaceflinger/tests/surface/Android.mk
@@ -9,7 +9,7 @@
 	libutils \
 	libbinder \
     libui \
-    libsurfaceflinger_client
+    libgui
 
 LOCAL_MODULE:= test-surface
 
diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp
index 67ecf7e..5265f91 100644
--- a/services/surfaceflinger/tests/surface/surface.cpp
+++ b/services/surfaceflinger/tests/surface/surface.cpp
@@ -53,7 +53,7 @@
     printf("window=%p\n", window);
 
     int err = native_window_set_buffer_count(window, 8);
-    android_native_buffer_t* buffer;
+    ANativeWindowBuffer* buffer;
 
     for (int i=0 ; i<8 ; i++) {
         window->dequeueBuffer(window, &buffer);