Merge commit 'goog/master' into merge_master
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 9c94c2e..d31d81c 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -12,6 +12,8 @@
 	endif
 endif
 
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libutils \
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index d565dc1..e2d01de 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BootAnimation"
-
 #include <stdint.h>
 #include <sys/types.h>
 #include <math.h>
@@ -35,7 +33,7 @@
 #include <ui/DisplayInfo.h>
 #include <ui/ISurfaceComposer.h>
 #include <ui/ISurfaceFlingerClient.h>
-#include <ui/EGLNativeWindowSurface.h>
+#include <ui/FramebufferNativeWindow.h>
 
 #include <core/SkBitmap.h>
 #include <images/SkImageDecoder.h>
@@ -130,12 +128,15 @@
         return -1;
 
     // create the native surface
-    sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h,
-            PIXEL_FORMAT_RGB_565, ISurfaceComposer::eGPU);
+    sp<SurfaceControl> control = session()->createSurface(
+            getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565,
+            ISurfaceComposer::eGPU);
     session()->openTransaction();
-    s->setLayer(0x40000000);
+    control->setLayer(0x40000000);
     session()->closeTransaction();
 
+    sp<Surface> s = control->getSurface();
+
     // initialize opengl and egl
     const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6,
             EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 0, EGL_NONE };
@@ -150,9 +151,7 @@
     eglInitialize(display, 0, 0);
     eglChooseConfig(display, attribs, &config, 1, &numConfigs);
 
-    mNativeWindowSurface = new EGLNativeWindowSurface(s);
-    surface = eglCreateWindowSurface(display, config, 
-            mNativeWindowSurface.get(), NULL);
+    surface = eglCreateWindowSurface(display, config, s.get(), NULL);
 
     context = eglCreateContext(display, config, NULL, NULL);
     eglQuerySurface(display, surface, EGL_WIDTH, &w);
@@ -163,6 +162,7 @@
     mSurface = surface;
     mWidth = w;
     mHeight = h;
+    mFlingerSurfaceControl = control;
     mFlingerSurface = s;
 
     // initialize GL
@@ -178,8 +178,8 @@
     eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglDestroyContext(mDisplay, mContext);
     eglDestroySurface(mDisplay, mSurface);
-    mNativeWindowSurface.clear();
     mFlingerSurface.clear();
+    mFlingerSurfaceControl.clear();
     eglTerminate(mDisplay);
     IPCThreadState::self()->stopProcess();
     return r;
@@ -200,8 +200,7 @@
     const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
 
     // draw and update only what we need
-    mNativeWindowSurface->setSwapRectangle(updateRect.left,
-            updateRect.top, updateRect.width(), updateRect.height());
+    mFlingerSurface->setSwapRectangle(updateRect);
 
     glEnable(GL_SCISSOR_TEST);
     glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 42e9eed..796077d 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -34,7 +34,6 @@
 namespace android {
 
 class AssetManager;
-class EGLNativeWindowSurface;
 
 // ---------------------------------------------------------------------------
 
@@ -68,8 +67,8 @@
     EGLDisplay  mDisplay;
     EGLDisplay  mContext;
     EGLDisplay  mSurface;
+    sp<SurfaceControl> mFlingerSurfaceControl;
     sp<Surface> mFlingerSurface;
-    sp<EGLNativeWindowSurface> mNativeWindowSurface;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 0178d63..a87c622 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -127,6 +127,8 @@
     @SuppressWarnings("unused")
     private int mSurface;
     @SuppressWarnings("unused")
+    private int mSurfaceControl;
+    @SuppressWarnings("unused")
     private int mSaveCount;
     @SuppressWarnings("unused")
     private Canvas mCanvas;
@@ -270,7 +272,7 @@
 
     @Override
     public String toString() {
-        return "Surface(native-token=" + mSurface + ")";
+        return "Surface(native-token=" + mSurfaceControl + ")";
     }
 
     private Surface(Parcel source) throws OutOfResourcesException {
@@ -283,7 +285,7 @@
 
     public native   void readFromParcel(Parcel source);
     public native   void writeToParcel(Parcel dest, int flags);
-
+    
     public static final Parcelable.Creator<Surface> CREATOR
             = new Parcelable.Creator<Surface>()
     {
@@ -304,7 +306,7 @@
     /* no user serviceable parts here ... */
     @Override
     protected void finalize() throws Throwable {
-        clear();
+        release();
     }
     
     private native void init(SurfaceSession s,
@@ -312,4 +314,6 @@
             throws OutOfResourcesException;
 
     private native void init(Parcel source);
+    
+    private native void release();
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 31cc4f7..f6f4c70 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -15,6 +15,8 @@
   LOCAL_CFLAGS += -DCUSTOM_RUNTIME_HEAP_MAX=$(USE_CUSTOM_RUNTIME_HEAP_MAX)
 endif
 
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
 LOCAL_SRC_FILES:= \
 	ActivityManager.cpp \
 	AndroidRuntime.cpp \
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 076775f..bd3c805 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -24,6 +24,7 @@
 
 #include <SkCanvas.h>
 #include <SkBitmap.h>
+#include <SkRegion.h>
 
 #include "jni.h"
 #include <android_runtime/AndroidRuntime.h>
@@ -45,6 +46,7 @@
 static sso_t sso;
 
 struct so_t {
+    jfieldID surfaceControl;
     jfieldID surface;
     jfieldID saveCount;
     jfieldID canvas;
@@ -121,10 +123,50 @@
 
 // ----------------------------------------------------------------------------
 
+static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz)
+{
+    SurfaceControl* const p = 
+        (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
+    return sp<SurfaceControl>(p);
+}
+
+static void setSurfaceControl(JNIEnv* env, jobject clazz, 
+        const sp<SurfaceControl>& surface)
+{
+    SurfaceControl* const p = 
+        (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
+    if (surface.get()) {
+        surface->incStrong(clazz);
+    }
+    if (p) {
+        p->decStrong(clazz);
+    }
+    env->SetIntField(clazz, so.surfaceControl, (int)surface.get());
+}
+
 static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
 {
-    Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
-    return sp<Surface>(p);
+    sp<Surface> result((Surface*)env->GetIntField(clazz, so.surface));
+    if (result == 0) {
+        /*
+         * if this method is called from the WindowManager's process, it means
+         * the client is is not remote, and therefore is allowed to have
+         * a Surface (data), so we create it here. 
+         * If we don't have a SurfaceControl, it means we're in a different
+         * process.
+         */
+        
+        SurfaceControl* const control = 
+            (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
+        if (control) {
+            result = control->getSurface();
+            if (result != 0) {
+                result->incStrong(clazz);
+                env->SetIntField(clazz, so.surface, (int)result.get());
+            }
+        }
+    }
+    return result;
 }
 
 static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
@@ -153,12 +195,12 @@
     SurfaceComposerClient* client =
             (SurfaceComposerClient*)env->GetIntField(session, sso.client);
 
-    sp<Surface> surface(client->createSurface(pid, dpy, w, h, format, flags));
+    sp<SurfaceControl> surface(client->createSurface(pid, dpy, w, h, format, flags));
     if (surface == 0) {
         doThrow(env, OutOfResourcesException);
         return;
     }
-    setSurface(env, clazz, surface);
+    setSurfaceControl(env, clazz, surface);
 }
 
 static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
@@ -168,19 +210,34 @@
         doThrow(env, "java/lang/NullPointerException", NULL);
         return;
     }
-    const sp<Surface>& rhs = Surface::readFromParcel(parcel);
+    sp<Surface> rhs = new Surface(*parcel);
     setSurface(env, clazz, rhs);
 }
 
 static void Surface_clear(JNIEnv* env, jobject clazz, uintptr_t *ostack)
 {
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (SurfaceControl::isValid(surface)) {
+        surface->clear();
+    }
+    setSurfaceControl(env, clazz, 0);
+    setSurface(env, clazz, 0);
+}
+
+static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack)
+{
+    setSurfaceControl(env, clazz, 0);
     setSurface(env, clazz, 0);
 }
 
 static jboolean Surface_isValid(JNIEnv* env, jobject clazz)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    return surface->isValid() ? JNI_TRUE : JNI_FALSE;
+    const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz));
+    if (surfaceControl != 0) {
+        return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
+    }
+    const sp<Surface>& surface(getSurface(env, clazz));
+    return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
 }
 
 static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
@@ -200,8 +257,8 @@
 
 static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (!surface->isValid())
+    const sp<Surface>& surface(getSurface(env, clazz));
+    if (!Surface::isValid(surface))
         return 0;
 
     // get dirty region
@@ -212,7 +269,7 @@
         dirty.top   = env->GetIntField(dirtyRect, ro.t);
         dirty.right = env->GetIntField(dirtyRect, ro.r);
         dirty.bottom= env->GetIntField(dirtyRect, ro.b);
-        if (dirty.left < dirty.right && dirty.top < dirty.bottom) {
+        if (!dirty.isEmpty()) {
             dirtyRegion.set(dirty);    
         }
     } else {
@@ -235,7 +292,8 @@
 
     SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
     SkBitmap bitmap;
-    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, info.bpr);
+    ssize_t bpr = info.s * bytesPerPixel(info.format);
+    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
     if (info.w > 0 && info.h > 0) {
         bitmap.setPixels(info.bits);
     } else {
@@ -243,13 +301,27 @@
         bitmap.setPixels(NULL);
     }
     nativeCanvas->setBitmapDevice(bitmap);
-    nativeCanvas->clipRegion(dirtyRegion.toSkRegion());
+    
+    SkRegion clipReg;
+    if (dirtyRegion.isRect()) { // very common case
+        const Rect& b(dirtyRegion.getBounds());
+        clipReg.setRect(b.left, b.top, b.right, b.bottom);
+    } else {
+        size_t count;
+        Rect const* r = dirtyRegion.getArray(&count);
+        while (count) {
+            clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
+            r++, count--;
+        }
+    }
+
+    nativeCanvas->clipRegion(clipReg);
     
     int saveCount = nativeCanvas->save();
     env->SetIntField(clazz, so.saveCount, saveCount);
 
     if (dirtyRect) {
-        Rect bounds(dirtyRegion.bounds());
+        const Rect& bounds(dirtyRegion.getBounds());
         env->SetIntField(dirtyRect, ro.l, bounds.left);
         env->SetIntField(dirtyRect, ro.t, bounds.top);
         env->SetIntField(dirtyRect, ro.r, bounds.right);
@@ -268,8 +340,8 @@
         return;
     }
     
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (!surface->isValid())
+    const sp<Surface>& surface(getSurface(env, clazz));
+    if (!Surface::isValid(surface))
         return;
 
     // detach the canvas from the surface
@@ -289,26 +361,8 @@
 static void Surface_unlockCanvas(
         JNIEnv* env, jobject clazz, jobject argCanvas)
 {
-    jobject canvas = env->GetObjectField(clazz, so.canvas);
-    if (canvas != argCanvas) {
-        doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        return;
-    }
-    
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (!surface->isValid())
-        return;
-    
-    status_t err = surface->unlock();
-    if (err < 0) {
-        doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        return;
-    }
-    SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
-    int saveCount = env->GetIntField(clazz, so.saveCount);
-    nativeCanvas->restoreToCount(saveCount);
-    nativeCanvas->setBitmapDevice(SkBitmap());
-    env->SetIntField(clazz, so.saveCount, 0);
+    // XXX: this API has been removed
+    doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_openTransaction(
@@ -353,138 +407,140 @@
 static void Surface_setLayer(
         JNIEnv* env, jobject clazz, jint zorder)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->setLayer(zorder) < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->setLayer(zorder);
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_setPosition(
         JNIEnv* env, jobject clazz, jint x, jint y)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->setPosition(x, y) < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->setPosition(x, y);
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_setSize(
         JNIEnv* env, jobject clazz, jint w, jint h)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->setSize(w, h) < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->setSize(w, h);
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_hide(
         JNIEnv* env, jobject clazz)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->hide() < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->hide();
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_show(
         JNIEnv* env, jobject clazz)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->show() < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->show();
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_freeze(
         JNIEnv* env, jobject clazz)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->freeze() < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->freeze();
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_unfreeze(
         JNIEnv* env, jobject clazz)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->unfreeze() < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->unfreeze();
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_setFlags(
         JNIEnv* env, jobject clazz, jint flags, jint mask)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->setFlags(flags, mask) < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->setFlags(flags, mask);
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_setTransparentRegion(
         JNIEnv* env, jobject clazz, jobject argRegion)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
-        if (surface->setTransparentRegionHint(Region(*nativeRegion)) < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
+    
+    const SkIRect& b(nativeRegion->getBounds());
+    Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
+    if (nativeRegion->isComplex()) {
+        SkRegion::Iterator it(*nativeRegion);
+        while (!it.done()) {
+            const SkIRect& r(it.rect());
+            reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
+            it.next();
         }
     }
+    
+    status_t err = surface->setTransparentRegionHint(reg);
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_setAlpha(
         JNIEnv* env, jobject clazz, jfloat alpha)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->setAlpha(alpha) < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->setAlpha(alpha);
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_setMatrix(
         JNIEnv* env, jobject clazz,
         jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->setMatrix(dsdx, dtdx, dsdy, dtdy) < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
 static void Surface_setFreezeTint(
         JNIEnv* env, jobject clazz,
         jint tint)
 {
-    const sp<Surface>& surface = getSurface(env, clazz);
-    if (surface->isValid()) {
-        if (surface->setFreezeTint(tint) < 0) {
-            doThrow(env, "java/lang/IllegalArgumentException", NULL);
-        }
-    }
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
+    if (surface == 0) return;
+    status_t err = surface->setFreezeTint(tint);
+    if (err<0 && err!=NO_INIT)
+        doThrow(env, "java/lang/IllegalArgumentException", NULL);
 }
 
+// ----------------------------------------------------------------------------
+
 static void Surface_copyFrom(
         JNIEnv* env, jobject clazz, jobject other)
 {
@@ -496,16 +552,21 @@
         return;
     }
 
-    const sp<Surface>& surface = getSurface(env, clazz);
-    const sp<Surface>& rhs = getSurface(env, other);
-    if (!Surface::isSameSurface(surface, rhs)) {
+    /*
+     * This is used by the WindowManagerService just after constructing
+     * a Surface and is necessary for returning the Surface reference to
+     * the caller. At this point, we should only have a SurfaceControl.
+     */
+    
+    const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
+    const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
+    if (!SurfaceControl::isSameSurface(surface, rhs)) {
         // we reassign the surface only if it's a different one
         // otherwise we would loose our client-side state.
-        setSurface(env, clazz, rhs->dup());
+        setSurfaceControl(env, clazz, rhs);
     }
 }
 
-
 static void Surface_readFromParcel(
         JNIEnv* env, jobject clazz, jobject argParcel)
 {
@@ -515,9 +576,9 @@
         return;
     }
 
-    const sp<Surface>& surface = getSurface(env, clazz);
-    const sp<Surface>& rhs = Surface::readFromParcel(parcel);
-    if (!Surface::isSameSurface(surface, rhs)) {
+    const sp<Surface>& control(getSurface(env, clazz));
+    sp<Surface> rhs = new Surface(*parcel);
+    if (!Surface::isSameSurface(control, rhs)) {
         // we reassign the surface only if it's a different one
         // otherwise we would loose our client-side state.
         setSurface(env, clazz, rhs);
@@ -535,8 +596,8 @@
         return;
     }
 
-    const sp<Surface>& surface = getSurface(env, clazz);
-    Surface::writeToParcel(surface, parcel);
+    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
+    SurfaceControl::writeSurfaceToParcel(control, parcel);
 }
 
 // ----------------------------------------------------------------------------
@@ -557,7 +618,8 @@
     {"nativeClassInit",     "()V",  (void*)nativeClassInit },
     {"init",                "(Landroid/view/SurfaceSession;IIIIII)V",  (void*)Surface_init },
     {"init",                "(Landroid/os/Parcel;)V",  (void*)Surface_initParcel },
-	{"clear",               "()V",  (void*)Surface_clear },
+    {"clear",               "()V",  (void*)Surface_clear },
+    {"release",             "()V",  (void*)Surface_release },
 	{"copyFrom",            "(Landroid/view/Surface;)V",  (void*)Surface_copyFrom },
 	{"isValid",             "()Z",  (void*)Surface_isValid },
 	{"lockCanvasNative",    "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",  (void*)Surface_lockCanvas },
@@ -586,7 +648,8 @@
 
 void nativeClassInit(JNIEnv* env, jclass clazz)
 {
-	so.surface   = env->GetFieldID(clazz, "mSurface", "I");
+    so.surface = env->GetFieldID(clazz, "mSurface", "I");
+    so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
 	so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
 	so.canvas    = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
 
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 4452065..974fc0b 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -21,7 +21,6 @@
 #include <EGL/egl.h>
 #include <GLES/gl.h>
 
-#include <ui/EGLNativeWindowSurface.h>
 #include <ui/Surface.h>
 #include <SkBitmap.h>
 #include <SkPixelRef.h>
@@ -338,7 +337,7 @@
         goto not_valid_surface;
 
     jint* base = beginNativeAttribList(_env, attrib_list);
-    EGLSurface sur = eglCreateWindowSurface(dpy, cnf, new EGLNativeWindowSurface(window), base);
+    EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window, base);
     endNativeAttributeList(_env, attrib_list, base);
     return (jint)sur;
 }
diff --git a/core/res/res/drawable/stat_sys_signal_flightmode.png b/core/res/res/drawable/stat_sys_signal_flightmode.png
old mode 100644
new mode 100755
Binary files differ
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index d057556..6628f75 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -126,13 +126,22 @@
             mFirst = mLast = newNode;
             newNode->prev = newNode->next = 0;
         } else {
-            insertBefore(mFirst, newNode);
+            newNode->prev = 0;
+            newNode->next = mFirst;
+            mFirst->prev = newNode;
+            mFirst = newNode;
         }
     }
     
     void insertTail(NODE* newNode) {
-        if (mLast == 0) insertBeginning(newNode);
-        else            insertAfter(mLast, newNode);
+        if (mLast == 0) {
+            insertHead(newNode);
+        } else {
+            newNode->prev = mLast;
+            newNode->next = 0;
+            mLast->next = newNode;
+            mLast = newNode;
+        }
     }
 
     NODE* remove(NODE* node) {
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 0c7ad46..641961f 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -26,6 +26,7 @@
 #endif
 
 #include <private/pixelflinger/ggl_context.h>
+#include <hardware/copybit.h>
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
@@ -39,7 +40,7 @@
 class EGLBufferObjectManager;
 
 namespace gl {
- 
+
 struct ogles_context_t;
 struct matrixx_t;
 struct transform_t;
@@ -96,7 +97,7 @@
 
 struct vertex_t {
     enum {
-        // these constant matter for our clipping 
+        // these constant matter for our clipping
         CLIP_L          = 0x0001,   // clipping flags
         CLIP_R          = 0x0002,
         CLIP_B          = 0x0004,
@@ -106,7 +107,7 @@
 
         EYE             = 0x0040,
         RESERVED        = 0x0080,
-        
+
         USER_CLIP_0     = 0x0100,   // user clipping flags
         USER_CLIP_1     = 0x0200,
         USER_CLIP_2     = 0x0400,
@@ -121,7 +122,7 @@
         USER_CLIP_ALL   = 0x3F00,
         CLIP_ALL        = 0x3F3F,
     };
-    
+
     // the fields below are arranged to minimize d-cache usage
     // we group together, by cache-line, the fields most likely to be used
 
@@ -130,7 +131,7 @@
     vec4_t          eye;
     };
     vec4_t          clip;
-    
+
     uint32_t        flags;
     size_t          index;  // cache tag, and vertex index
     GLfixed         fog;
@@ -142,7 +143,7 @@
     vec4_t          color;
     vec4_t          texture[GGL_TEXTURE_UNIT_COUNT];
     uint32_t        reserved1[4];
-    
+
     inline void clear() {
         flags = index = locked = mru = 0;
     }
@@ -199,7 +200,7 @@
     GLenum          indicesType;
     buffer_t const* array_buffer;
     buffer_t const* element_array_buffer;
-    
+
     void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei);
     void (*compileElement)(ogles_context_t*, vertex_t*, GLint);
 
@@ -410,7 +411,7 @@
     matrixx_t       matrix;
     uint32_t        flags;
     uint32_t        ops;
-    
+
     union {
         struct {
             void (*point2)(transform_t const* t, vec4_t*, vec4_t const*);
@@ -509,17 +510,17 @@
     GLint       x;
     GLint       y;
     GLsizei     w;
-    GLsizei     h; 
+    GLsizei     h;
     struct {
         GLint       x;
         GLint       y;
-    } surfaceport;  
+    } surfaceport;
     struct {
         GLint       x;
         GLint       y;
         GLsizei     w;
-        GLsizei     h; 
-    } scissor;  
+        GLsizei     h;
+    } scissor;
 };
 
 // ----------------------------------------------------------------------------
@@ -594,6 +595,16 @@
     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;
+    // File descriptor of current drawing surface, if it's suitable for use as
+    // a copybits destination, else -1.
+    int                     drawSurfaceFd;
+};
+
 struct ogles_context_t {
     context_t               rasterizer;
     array_machine_t         arrays         __attribute__((aligned(32)));
@@ -617,6 +628,14 @@
     uint32_t                transformTextures : 1;
     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/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
new file mode 100644
index 0000000..6c847ff
--- /dev/null
+++ b/include/private/ui/RegionHelper.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_UI_PRIVATE_REGION_HELPER_H
+#define ANDROID_UI_PRIVATE_REGION_HELPER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+template<typename RECT>
+class region_operator
+{
+    typedef typename RECT::value_type TYPE;    
+    static const TYPE max_value = 0x7FFFFFF;
+
+public:
+    /* 
+     * Common boolean operations:
+     * value is computed as 0b101 op 0b110
+     *    other boolean operation are possible, simply compute
+     *    their corresponding value with the above formulae and use
+     *    it when instantiating a region_operator.
+     */
+    static const uint32_t LHS = 0x5;  // 0b101
+    static const uint32_t RHS = 0x6;  // 0b110
+    enum {
+        op_nand = LHS & ~RHS,
+        op_and  = LHS &  RHS,
+        op_or   = LHS |  RHS,
+        op_xor  = LHS ^  RHS
+    };
+
+    struct region {
+        RECT const* rects;
+        size_t count;
+        TYPE dx;
+        TYPE dy;
+        inline region(const region& rhs) 
+            : rects(rhs.rects), count(rhs.count), dx(rhs.dx), dy(rhs.dy) { }
+        inline region(RECT const* r, size_t c) 
+            : rects(r), count(c), dx(), dy() { }
+        inline region(RECT const* r, size_t c, TYPE dx, TYPE dy) 
+            : rects(r), count(c), dx(dx), dy(dy) { }
+    };
+
+    class region_rasterizer {
+        friend class region_operator;
+        virtual void operator()(const RECT& rect) = 0;
+    };
+    
+    inline region_operator(int op, const region& lhs, const region& rhs) 
+        : op_mask(op), spanner(lhs, rhs) 
+    {
+    }
+
+    void operator()(region_rasterizer& rasterizer) {
+        RECT current;
+        do {
+            SpannerInner spannerInner(spanner.lhs, spanner.rhs);
+            int inside = spanner.next(current.top, current.bottom);
+            spannerInner.prepare(inside);
+            do {
+                TYPE left, right;
+                int inside = spannerInner.next(current.left, current.right);
+                if ((op_mask >> inside) & 1) {
+                    if (current.left < current.right && 
+                            current.top < current.bottom) {
+                        rasterizer(current);
+                    }
+                }
+            } while(!spannerInner.isDone());            
+        } while(!spanner.isDone());
+    }
+
+private:    
+    uint32_t op_mask;
+
+    class SpannerBase
+    {
+    public:
+        enum {
+            lhs_before_rhs   = 0,
+            lhs_after_rhs    = 1,
+            lhs_coincide_rhs = 2
+        };
+
+    protected:
+        TYPE lhs_head;
+        TYPE lhs_tail;
+        TYPE rhs_head;
+        TYPE rhs_tail;
+
+        inline int next(TYPE& head, TYPE& tail,
+                bool& more_lhs, bool& more_rhs) 
+        {
+            int inside;
+            more_lhs = false;
+            more_rhs = false;
+            if (lhs_head < rhs_head) {
+                inside = lhs_before_rhs;
+                head = lhs_head;
+                if (lhs_tail <= rhs_head) {
+                    tail = lhs_tail;
+                    more_lhs = true;
+                } else {
+                    lhs_head = rhs_head;
+                    tail = rhs_head;
+                }
+            } else if (rhs_head < lhs_head) {
+                inside = lhs_after_rhs;
+                head = rhs_head;
+                if (rhs_tail <= lhs_head) {
+                    tail = rhs_tail;
+                    more_rhs = true;
+                } else {
+                    rhs_head = lhs_head;
+                    tail = lhs_head;
+                }
+            } else {
+                inside = lhs_coincide_rhs;
+                head = lhs_head;
+                if (lhs_tail <= rhs_tail) {
+                    tail = rhs_head = lhs_tail;
+                    more_lhs = true;
+                }
+                if (rhs_tail <= lhs_tail) {
+                    tail = lhs_head = rhs_tail;
+                    more_rhs = true;
+                }
+            }
+            return inside;
+        }
+    };
+
+    class Spanner : protected SpannerBase 
+    {
+        friend class region_operator;
+        region lhs;
+        region rhs;
+
+    public:
+        inline Spanner(const region& lhs, const region& rhs)
+            : lhs(lhs), rhs(rhs) 
+        {
+            SpannerBase::lhs_head = lhs.rects->top      + lhs.dy;
+            SpannerBase::lhs_tail = lhs.rects->bottom   + lhs.dy;
+            SpannerBase::rhs_head = rhs.rects->top      + rhs.dy;
+            SpannerBase::rhs_tail = rhs.rects->bottom   + rhs.dy;
+        }
+
+        inline bool isDone() const {
+            return !rhs.count && !lhs.count;
+        }
+
+        inline int next(TYPE& top, TYPE& bottom) 
+        {
+            bool more_lhs = false;
+            bool more_rhs = false;
+            int inside = SpannerBase::next(top, bottom, more_lhs, more_rhs);
+            if (more_lhs) {
+                advance(lhs, SpannerBase::lhs_head, SpannerBase::lhs_tail);
+            }
+            if (more_rhs) {
+                advance(rhs, SpannerBase::rhs_head, SpannerBase::rhs_tail);
+            }
+            return inside;
+        }
+
+    private:
+        static inline 
+        void advance(region& reg, TYPE& aTop, TYPE& aBottom) {
+            // got to next span
+            size_t count = reg.count;
+            RECT const * rects = reg.rects;
+            RECT const * const end = rects + count;
+            const int top = rects->top;
+            while (rects != end && rects->top == top) {
+                rects++;
+                count--;
+            }
+            if (rects != end) {
+                aTop    = rects->top    + reg.dy;
+                aBottom = rects->bottom + reg.dy;
+            } else {
+                aTop    = max_value;
+                aBottom = max_value;
+            }
+            reg.rects = rects;
+            reg.count = count;
+        }
+    };
+
+    class SpannerInner : protected SpannerBase 
+    {
+        region lhs;
+        region rhs;
+        
+    public:
+        inline SpannerInner(const region& lhs, const region& rhs)
+            : lhs(lhs), rhs(rhs) 
+        {
+        }
+
+        inline void prepare(int inside) {
+            SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+            SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+            SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+            SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+            if (inside == SpannerBase::lhs_before_rhs) {
+                SpannerBase::rhs_head = max_value;
+                SpannerBase::rhs_tail = max_value;
+            } else if (inside == SpannerBase::lhs_after_rhs) {
+                SpannerBase::lhs_head = max_value;
+                SpannerBase::lhs_tail = max_value;
+            } else {
+                // use both spans
+            }
+        }
+
+        inline bool isDone() const {
+            return SpannerBase::lhs_head == max_value && 
+                   SpannerBase::rhs_head == max_value;
+        }
+
+        inline int next(TYPE& left, TYPE& right) 
+        {
+            bool more_lhs = false;
+            bool more_rhs = false;
+            int inside = SpannerBase::next(left, right, more_lhs, more_rhs);
+            if (more_lhs) {
+                advance(lhs, SpannerBase::lhs_head, SpannerBase::lhs_tail);
+            }
+            if (more_rhs) {
+                advance(rhs, SpannerBase::rhs_head, SpannerBase::rhs_tail);
+            }
+            return inside;
+        }
+
+    private:
+        static inline 
+        void advance(region& reg, TYPE& left, TYPE& right) {
+            if (reg.rects && reg.count) {
+                const int cur_span_top = reg.rects->top;
+                reg.rects++;
+                reg.count--;
+                if (!reg.count || reg.rects->top != cur_span_top) {
+                    left  = max_value;
+                    right = max_value;
+                } else {
+                    left  = reg.rects->left  + reg.dx;
+                    right = reg.rects->right + reg.dx;
+                }
+            }
+        }
+    };
+
+    Spanner spanner;
+};
+
+// ----------------------------------------------------------------------------
+};
+
+#endif /* ANDROID_UI_PRIVATE_REGION_HELPER_H */
diff --git a/include/private/ui/SharedState.h b/include/private/ui/SharedState.h
index 546d0ad..3bc7979 100644
--- a/include/private/ui/SharedState.h
+++ b/include/private/ui/SharedState.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <utils/Debug.h>
 #include <utils/threads.h>
 
 namespace android {
@@ -32,16 +33,12 @@
 
 struct surface_info_t { // 4 longs, 16 bytes
     enum {
-        eBufferDirty    = 0x01
+        eBufferDirty    = 0x01,
+        eNeedNewBuffer  = 0x02
     };
-    uint16_t    w;
-    uint16_t    h;
-    uint16_t    stride;
-    uint16_t    bpr;
-    uint16_t    reserved;
-    uint8_t     format;
+    uint8_t     reserved[11];
     uint8_t     flags;
-    ssize_t     bits_offset;
+    status_t    status;
 };
 
 // ---------------------------------------------------------------------------
@@ -110,8 +107,6 @@
         INSPECT  = 0x00000002
     };
 
-    per_client_cblk_t();
-
     // these functions are used by the clients
     status_t validate(size_t i) const;
     int32_t lock_layer(size_t i, uint32_t flags);
@@ -138,30 +133,19 @@
 
 struct surface_flinger_cblk_t   // 4KB max
 {
-    surface_flinger_cblk_t();
-    
     uint8_t         connected;
     uint8_t         reserved[3];
     uint32_t        pad[7];
- 
     display_cblk_t  displays[NUM_DISPLAY_MAX];
 };
 
 // ---------------------------------------------------------------------------
 
-template<bool> struct CTA;
-template<> struct CTA<true> { };
+COMPILE_TIME_ASSERT(sizeof(layer_cblk_t) == 128)
+COMPILE_TIME_ASSERT(sizeof(per_client_cblk_t) <= 4096)
+COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
 
-// compile-time assertions. just to avoid catastrophes.
-inline void compile_time_asserts() {
-    CTA<sizeof(layer_cblk_t) == 128> sizeof__layer_cblk_t__eq_128;
-    (void)sizeof__layer_cblk_t__eq_128; // we don't want a warning
-    CTA<sizeof(per_client_cblk_t) <= 4096> sizeof__per_client_cblk_t__le_4096;
-    (void)sizeof__per_client_cblk_t__le_4096;  // we don't want a warning
-    CTA<sizeof(surface_flinger_cblk_t) <= 4096> sizeof__surface_flinger_cblk_t__le_4096;
-    (void)sizeof__surface_flinger_cblk_t__le_4096;  // we don't want a warning
-}
-
+// ---------------------------------------------------------------------------
 }; // namespace android
 
 #endif // ANDROID_UI_SHARED_STATE_H
diff --git a/include/private/ui/SurfaceBuffer.h b/include/private/ui/SurfaceBuffer.h
new file mode 100644
index 0000000..c45abeb
--- /dev/null
+++ b/include/private/ui/SurfaceBuffer.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_PRIVATE_SURFACE_BUFFER_H
+#define ANDROID_UI_PRIVATE_SURFACE_BUFFER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+
+#include <private/ui/android_natives_priv.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class BufferMapper;
+class Rect;
+class Surface;
+class SurfaceBuffer;
+
+// ---------------------------------------------------------------------------
+
+class SurfaceBuffer 
+    : public EGLNativeBase<
+        android_native_buffer_t, 
+        SurfaceBuffer, 
+        LightRefBase<SurfaceBuffer> >
+{
+public:
+    status_t lock(uint32_t usage, void** vaddr);
+    status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
+    status_t unlock();
+
+protected:
+            SurfaceBuffer();
+            SurfaceBuffer(const Parcel& reply);
+    virtual ~SurfaceBuffer();
+    bool mOwner;
+
+    inline const BufferMapper& getBufferMapper() const { return mBufferMapper; }
+    inline BufferMapper& getBufferMapper() { return mBufferMapper; }
+    
+private:
+    friend class Surface;
+    friend class BpSurface;
+    friend class BnSurface;
+    friend class LightRefBase<SurfaceBuffer>;    
+
+    SurfaceBuffer& operator = (const SurfaceBuffer& rhs);
+    const SurfaceBuffer& operator = (const SurfaceBuffer& rhs) const;
+
+    static status_t writeToParcel(Parcel* reply, 
+            android_native_buffer_t const* buffer);
+    
+    BufferMapper& mBufferMapper;
+};
+
+}; // namespace android
+
+#endif // ANDROID_UI_PRIVATE_SURFACE_BUFFER_H
+
diff --git a/include/private/ui/SurfaceFlingerSynchro.h b/include/private/ui/SurfaceFlingerSynchro.h
index ff91b61..7386d33 100644
--- a/include/private/ui/SurfaceFlingerSynchro.h
+++ b/include/private/ui/SurfaceFlingerSynchro.h
@@ -21,7 +21,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 #include <utils/Errors.h>
-#include <utils/threads.h>
 #include <ui/ISurfaceComposer.h>
 
 namespace android {
@@ -31,7 +30,6 @@
 class SurfaceFlingerSynchro
 {
 public:
-
                 // client constructor
                 SurfaceFlingerSynchro(const sp<ISurfaceComposer>& flinger);
                 ~SurfaceFlingerSynchro();
@@ -40,34 +38,8 @@
     status_t    signal();
     
 private:
-    class Barrier {
-    public:
-        Barrier();
-        ~Barrier();
-        void open();
-        void close();
-        void waitAndClose();
-        status_t waitAndClose(nsecs_t timeout);
-    private:
-        enum { OPENED, CLOSED };
-        mutable     Mutex       lock;
-        mutable     Condition   cv;
-        volatile    int         state;
-    };
-
     friend class SurfaceFlinger;
-
-                // server constructor
-                SurfaceFlingerSynchro();
-                
-    void        open();
-    
-                // wait until there is some work to do
-    status_t    wait();
-    status_t    wait(nsecs_t timeout);
-    
     sp<ISurfaceComposer> mSurfaceComposer;
-    Barrier              mBarrier;
 };
 
 }; // namespace android
diff --git a/include/private/ui/android_natives_priv.h b/include/private/ui/android_natives_priv.h
new file mode 100644
index 0000000..ee843e9
--- /dev/null
+++ b/include/private/ui/android_natives_priv.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_ANDROID_NATIVES_PRIV_H
+#define ANDROID_ANDROID_NATIVES_PRIV_H
+
+#include <ui/egl/android_natives.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+
+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));
+    }
+#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];
+};
+
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*****************************************************************************/
+
+#endif /* ANDROID_ANDROID_NATIVES_PRIV_H */
diff --git a/include/ui/BufferMapper.h b/include/ui/BufferMapper.h
new file mode 100644
index 0000000..5f084be
--- /dev/null
+++ b/include/ui/BufferMapper.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_BUFFER_MAPPER_H
+#define ANDROID_UI_BUFFER_MAPPER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Singleton.h>
+
+#include <hardware/gralloc.h>
+
+
+struct gralloc_module_t;
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class Rect;
+
+class BufferMapper : public Singleton<BufferMapper>
+{
+public:
+    static inline BufferMapper& get() { return getInstance(); }
+
+    status_t registerBuffer(buffer_handle_t handle);
+
+    status_t unregisterBuffer(buffer_handle_t handle);
+    
+    status_t lock(buffer_handle_t handle,
+            int usage, const Rect& bounds, void** vaddr);
+
+    status_t unlock(buffer_handle_t handle);
+    
+    // dumps information about the mapping of this handle
+    void dump(buffer_handle_t handle);
+
+private:
+    friend class Singleton<BufferMapper>;
+    BufferMapper();
+    gralloc_module_t const *mAllocMod;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_UI_BUFFER_MAPPER_H
+
diff --git a/include/ui/EGLDisplaySurface.h b/include/ui/EGLDisplaySurface.h
deleted file mode 100644
index a8b5853..0000000
--- a/include/ui/EGLDisplaySurface.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_EGL_DISPLAY_SURFACE_H
-#define ANDROID_EGL_DISPLAY_SURFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Timers.h>
-
-#include <ui/EGLNativeSurface.h>
-
-#include <pixelflinger/pixelflinger.h>
-#include <linux/fb.h>
-
-#include <EGL/egl.h>
-
-struct copybit_device_t;
-struct copybit_image_t;
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class Region;
-class Rect;
-
-class EGLDisplaySurface : public EGLNativeSurface<EGLDisplaySurface>
-{
-public:
-    EGLDisplaySurface();
-    ~EGLDisplaySurface();
-    
-    int32_t getPageFlipCount() const;
-    void    copyFrontToBack(const Region& copyback);
-    void    copyFrontToImage(const copybit_image_t& dst);
-    void    copyBackToImage(const copybit_image_t& dst);
-    
-    void        setSwapRectangle(int l, int t, int w, int h);
-
-private:
-    static void         hook_incRef(NativeWindowType window);
-    static void         hook_decRef(NativeWindowType window);
-    static uint32_t     hook_swapBuffers(NativeWindowType window);
-     
-            uint32_t    swapBuffers();
-
-            status_t    mapFrameBuffer();
-
-            enum {
-                PAGE_FLIP = 0x00000001
-            };
-    GGLSurface          mFb[2];
-    int                 mIndex;
-    uint32_t            mFlags;
-    size_t              mSize;
-    fb_var_screeninfo   mInfo;
-    fb_fix_screeninfo   mFinfo;
-    int32_t             mPageFlipCount;
-    nsecs_t             mTime;
-    int32_t             mSwapCount;
-    nsecs_t             mSleep;
-    uint32_t            mFeatureFlags;
-    copybit_device_t*   mBlitEngine;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_EGL_DISPLAY_SURFACE_H
-
diff --git a/include/ui/EGLNativeWindowSurface.h b/include/ui/EGLNativeWindowSurface.h
deleted file mode 100644
index 3494234..0000000
--- a/include/ui/EGLNativeWindowSurface.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
-#define ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <ui/EGLNativeSurface.h>
-#include <EGL/egl.h>
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class Surface;
-
-class EGLNativeWindowSurface : public EGLNativeSurface<EGLNativeWindowSurface>
-{
-public:
-    EGLNativeWindowSurface(const sp<Surface>& surface);
-    ~EGLNativeWindowSurface();
-
-    void        setSwapRectangle(int l, int t, int w, int h);
-
-private:
-    static void         hook_incRef(NativeWindowType window);
-    static void         hook_decRef(NativeWindowType window);
-    static uint32_t     hook_swapBuffers(NativeWindowType window);
-    static void         hook_connect(NativeWindowType window);
-    static void         hook_disconnect(NativeWindowType window);
-
-            uint32_t    swapBuffers();
-            void        connect();
-            void        disconnect();
-            
-            sp<Surface> mSurface;
-            bool        mConnected;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
-
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
new file mode 100644
index 0000000..a780472
--- /dev/null
+++ b/include/ui/FramebufferNativeWindow.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
+#define ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <EGL/egl.h>
+
+#include <utils/threads.h>
+#include <ui/Rect.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+#include <ui/egl/android_natives.h>
+
+
+extern "C" EGLNativeWindowType android_createDisplaySurface(void);
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Surface;
+class NativeBuffer;
+
+// ---------------------------------------------------------------------------
+
+class FramebufferNativeWindow 
+    : public EGLNativeBase<
+        android_native_window_t, 
+        FramebufferNativeWindow, 
+        LightRefBase<FramebufferNativeWindow> >
+{
+public:
+    FramebufferNativeWindow(); 
+
+    framebuffer_device_t const * getDevice() const { return fbDev; } 
+
+    bool isUpdateOnDemand() const { return mUpdateOnDemand; }
+    status_t setUpdateRectangle(const Rect& updateRect);
+    
+private:
+    friend class LightRefBase<FramebufferNativeWindow>;    
+    ~FramebufferNativeWindow(); // this class cannot be overloaded
+    static int setSwapInterval(android_native_window_t* window, int interval);
+    static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
+    static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+    static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+    
+    framebuffer_device_t* fbDev;
+    alloc_device_t* grDev;
+
+    sp<NativeBuffer> buffers[2];
+    sp<NativeBuffer> front;
+    
+    mutable Mutex mutex;
+    Condition mCondition;
+    int32_t mNumBuffers;
+    int32_t mNumFreeBuffers;
+    int32_t mBufferHead;
+    bool mUpdateOnDemand;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
+
diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h
index 136e801..adba45a 100644
--- a/include/ui/ISurface.h
+++ b/include/ui/ISurface.h
@@ -26,6 +26,7 @@
 #include <ui/PixelFormat.h>
 
 #include <hardware/hardware.h>
+#include <hardware/gralloc.h>
 
 namespace android {
 
@@ -33,6 +34,7 @@
 
 class IMemoryHeap;
 class OverlayRef;
+class SurfaceBuffer;
 
 class ISurface : public IInterface
 {
@@ -42,11 +44,13 @@
         UNREGISTER_BUFFERS,
         POST_BUFFER, // one-way transaction
         CREATE_OVERLAY,
+        GET_BUFFER,
     };
 
 public: 
     DECLARE_META_INTERFACE(Surface);
 
+    virtual sp<SurfaceBuffer> getBuffer() = 0; 
     
     class BufferHeap {
     public:
@@ -78,9 +82,7 @@
     };
     
     virtual status_t registerBuffers(const BufferHeap& buffers) = 0;
-
     virtual void postBuffer(ssize_t offset) = 0; // one-way
-
     virtual void unregisterBuffers() = 0;
     
     virtual sp<OverlayRef> createOverlay(
diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h
index 5b062a8..ce2b94c 100644
--- a/include/ui/ISurfaceComposer.h
+++ b/include/ui/ISurfaceComposer.h
@@ -32,7 +32,6 @@
 // ----------------------------------------------------------------------------
 
 class DisplayInfo;
-class IGPUCallback;
 
 class ISurfaceComposer : public IInterface
 {
@@ -63,7 +62,6 @@
         eTransparentRegionChanged   = 0x00000020,
         eVisibilityChanged          = 0x00000040,
         eFreezeTintChanged          = 0x00000080,
-        eDestroyed                  = 0x00000100
     };
 
     enum {
@@ -112,37 +110,12 @@
      */
     virtual void bootFinished() = 0;
 
-    /* get access to the GPU. Access is relinquished when releasing regs */
-    struct gpu_info_t {
-        struct gpu_region_t {
-            sp<IMemory> region;
-            size_t reserved;
-        };
-        sp<IMemory>             regs;
-        size_t                  count;
-        gpu_region_t            regions[2];
-    };
-    virtual status_t requestGPU(
-            const sp<IGPUCallback>& callback,
-            gpu_info_t* gpu) = 0;
-
-    /* take the gpu back from any apps using it. They'll get a
-     * EGL_CONTEXT_LOST error */
-    virtual status_t revokeGPU() = 0;
-
     /* Signal surfaceflinger that there might be some work to do
      * This is an ASYNCHRONOUS call.
      */
     virtual void signal() const = 0;
 };
 
-class IGPUCallback : public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(GPUCallback);
-    virtual void gpuLost() = 0; //one-way
-};
-
 // ----------------------------------------------------------------------------
 
 class BnSurfaceComposer : public BnInterface<ISurfaceComposer>
@@ -159,8 +132,6 @@
         SET_ORIENTATION,
         FREEZE_DISPLAY,
         UNFREEZE_DISPLAY,
-        REQUEST_GPU,
-        REVOKE_GPU,
         SIGNAL
     };
 
@@ -170,15 +141,6 @@
                                     uint32_t flags = 0);
 };
 
-class BnGPUCallback : public BnInterface<IGPUCallback>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
 // ----------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/include/ui/ISurfaceFlingerClient.h b/include/ui/ISurfaceFlingerClient.h
index b6cbb0b..e93a4fa 100644
--- a/include/ui/ISurfaceFlingerClient.h
+++ b/include/ui/ISurfaceFlingerClient.h
@@ -52,7 +52,6 @@
     struct surface_data_t {
         int32_t             token;
         int32_t             identity;
-        sp<IMemoryHeap>     heap[2];
         status_t readFromParcel(const Parcel& parcel);
         status_t writeToParcel(Parcel* parcel) const;
     };
diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h
index 14af823..6d87321 100644
--- a/include/ui/PixelFormat.h
+++ b/include/ui/PixelFormat.h
@@ -84,6 +84,13 @@
 
 struct PixelFormatInfo
 {
+    enum {
+        INDEX_ALPHA   = 0,
+        INDEX_RED     = 1,
+        INDEX_GREEN   = 2,
+        INDEX_BLUE    = 3
+    };
+    
     enum { // components
         ALPHA               = 1,
         RGB                 = 2,
@@ -95,20 +102,33 @@
         Y_CB_CR_I           = 8,
     };
 
+    struct szinfo {
+        uint8_t h;
+        uint8_t l;
+    };
+    
     inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { }
     size_t getScanlineSize(unsigned int width) const;
+    size_t getSize(size_t ci) const { 
+        return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0;
+    }
     size_t      version;
     PixelFormat format;
     size_t      bytesPerPixel;
     size_t      bitsPerPixel;
-    uint8_t     h_alpha;
-    uint8_t     l_alpha;
-    uint8_t     h_red;
-    uint8_t     l_red;
-    uint8_t     h_green;
-    uint8_t     l_green;
-    uint8_t     h_blue;
-    uint8_t     l_blue;
+    union {
+        szinfo      cinfo[4];
+        struct {
+            uint8_t     h_alpha;
+            uint8_t     l_alpha;    
+            uint8_t     h_red;
+            uint8_t     l_red;
+            uint8_t     h_green;
+            uint8_t     l_green;
+            uint8_t     h_blue;
+            uint8_t     l_blue;
+        };
+    };
     uint8_t     components;
     uint8_t     reserved0[3];
     uint32_t    reserved1;
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index da72944..a213c09 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -30,6 +30,8 @@
     int right;
     int bottom;
 
+    typedef int value_type;
+
     // we don't provide copy-ctor and operator= on purpose
     // because we want the compiler generated versions
 
@@ -46,7 +48,11 @@
     }
 
     void makeInvalid();
-    
+
+    inline void clear() {
+        left = top = right = bottom = 0;
+    }
+
     // a valid rectangle has a non negative width and height
     inline bool isValid() const {
         return (width()>=0) && (height()>=0);
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 68cb52e..4299ea5 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -27,8 +27,6 @@
 
 #include <hardware/copybit.h>
 
-#include <core/SkRegion.h>
-
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -40,7 +38,6 @@
 public:
                         Region();
                         Region(const Region& rhs);
-    explicit            Region(const SkRegion& rhs);
     explicit            Region(const Rect& rhs);
     explicit            Region(const Parcel& parcel);
     explicit            Region(const void* buffer);
@@ -48,65 +45,75 @@
                         
         Region& operator = (const Region& rhs);
 
-    inline  bool        isEmpty() const     { return mRegion.isEmpty(); }
-    inline  bool        isRect() const      { return mRegion.isRect(); }
+    inline  bool        isEmpty() const     { return mBounds.isEmpty();  }
+    inline  bool        isRect() const      { return mStorage.isEmpty(); }
 
-            Rect        bounds() const;
-
-            const SkRegion& toSkRegion() const;
+    inline  const Rect& getBounds() const   { return mBounds; }
+    inline  const Rect& bounds() const      { return getBounds(); }
 
             void        clear();
             void        set(const Rect& r);
+            void        set(uint32_t w, uint32_t h);
         
             Region&     orSelf(const Rect& rhs);
             Region&     andSelf(const Rect& rhs);
+            Region&     subtractSelf(const Rect& rhs);
 
             // boolean operators, applied on this
             Region&     orSelf(const Region& rhs);
             Region&     andSelf(const Region& rhs);
             Region&     subtractSelf(const Region& rhs);
 
+            // boolean operators
+    const   Region      merge(const Rect& rhs) const;
+    const   Region      intersect(const Rect& rhs) const;
+    const   Region      subtract(const Rect& rhs) const;
+
+            // boolean operators
+    const   Region      merge(const Region& rhs) const;
+    const   Region      intersect(const Region& rhs) const;
+    const   Region      subtract(const Region& rhs) const;
+
             // these translate rhs first
             Region&     translateSelf(int dx, int dy);
             Region&     orSelf(const Region& rhs, int dx, int dy);
             Region&     andSelf(const Region& rhs, int dx, int dy);
             Region&     subtractSelf(const Region& rhs, int dx, int dy);
 
-            // boolean operators
-            Region      merge(const Region& rhs) const;
-            Region      intersect(const Region& rhs) const;
-            Region      subtract(const Region& rhs) const;
-
             // these translate rhs first
-            Region      translate(int dx, int dy) const;
-            Region      merge(const Region& rhs, int dx, int dy) const;
-            Region      intersect(const Region& rhs, int dx, int dy) const;
-            Region      subtract(const Region& rhs, int dx, int dy) const;
+    const   Region      translate(int dx, int dy) const;
+    const   Region      merge(const Region& rhs, int dx, int dy) const;
+    const   Region      intersect(const Region& rhs, int dx, int dy) const;
+    const   Region      subtract(const Region& rhs, int dx, int dy) const;
 
     // convenience operators overloads
-    inline  Region      operator | (const Region& rhs) const;
-    inline  Region      operator & (const Region& rhs) const;
-    inline  Region      operator - (const Region& rhs) const;
-    inline  Region      operator + (const Point& pt) const;
+    inline  const Region      operator | (const Region& rhs) const;
+    inline  const Region      operator & (const Region& rhs) const;
+    inline  const Region      operator - (const Region& rhs) const;
+    inline  const Region      operator + (const Point& pt) const;
 
     inline  Region&     operator |= (const Region& rhs);
     inline  Region&     operator &= (const Region& rhs);
     inline  Region&     operator -= (const Region& rhs);
     inline  Region&     operator += (const Point& pt);
 
-    class iterator {
-        SkRegion::Iterator  mIt;
-    public:
-        iterator(const Region& r);
-        inline operator bool () const { return !done(); }
-        int iterate(Rect* rect);
-    private:
-        inline bool done() const {
-            return const_cast<SkRegion::Iterator&>(mIt).done();
-        }
-    };
+    
+    /* various ways to access the rectangle list */
+    
+    typedef Rect const* const_iterator;
+    
+            const_iterator begin() const;
+            const_iterator end() const;
 
-            size_t      rects(Vector<Rect>& rectList) const;
+    /* no user serviceable parts here... */
+            
+            size_t      getRects(Vector<Rect>& rectList) const;
+            Rect const* getArray(size_t* count) const;
+
+            
+            // add a rectangle to the internal list. This rectangle must
+            // be sorted in Y and X and must not make the region invalid.
+            void        addRectUnchecked(int l, int t, int r, int b);
 
             // flatten/unflatten a region to/from a Parcel
             status_t    write(Parcel& parcel) const;
@@ -123,20 +130,46 @@
     void        dump(const char* what, uint32_t flags=0) const;
 
 private:
-    SkRegion    mRegion;
+    class rasterizer;
+    friend class rasterizer;
+    
+    Region& operationSelf(const Rect& r, int op);
+    Region& operationSelf(const Region& r, int op);
+    Region& operationSelf(const Region& r, int dx, int dy, int op);
+    const Region operation(const Rect& rhs, int op) const;
+    const Region operation(const Region& rhs, int op) const;
+    const Region operation(const Region& rhs, int dx, int dy, int op) const;
+
+    static void boolean_operation(int op, Region& dst,
+            const Region& lhs, const Region& rhs, int dx, int dy);
+    static void boolean_operation(int op, Region& dst,
+            const Region& lhs, const Rect& rhs, int dx, int dy);
+
+    static void boolean_operation(int op, Region& dst,
+            const Region& lhs, const Region& rhs);
+    static void boolean_operation(int op, Region& dst,
+            const Region& lhs, const Rect& rhs);
+
+    static void translate(Region& reg, int dx, int dy);
+    static void translate(Region& dst, const Region& reg, int dx, int dy);
+
+    static bool validate(const Region& reg, const char* name);
+    
+    Rect            mBounds;
+    Vector<Rect>    mStorage;
 };
 
 
-Region Region::operator | (const Region& rhs) const {
+const Region Region::operator | (const Region& rhs) const {
     return merge(rhs);
 }
-Region Region::operator & (const Region& rhs) const {
+const Region Region::operator & (const Region& rhs) const {
     return intersect(rhs);
 }
-Region Region::operator - (const Region& rhs) const {
+const Region Region::operator - (const Region& rhs) const {
     return subtract(rhs);
 }
-Region Region::operator + (const Point& pt) const {
+const Region Region::operator + (const Point& pt) const {
     return translate(pt.x, pt.y);
 }
 
@@ -157,16 +190,23 @@
 // ---------------------------------------------------------------------------
 
 struct region_iterator : public copybit_region_t {
-    region_iterator(const Region& region) : i(region) {
+    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) {
-        return static_cast<const region_iterator*>(self)
-        ->i.iterate(reinterpret_cast<Rect*>(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::iterator i;
+    mutable Region::const_iterator b;
+    Region::const_iterator const e;
 };
+
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 33953a9..8c4f63d 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -28,48 +28,40 @@
 #include <ui/Region.h>
 #include <ui/ISurfaceFlingerClient.h>
 
+#include <ui/egl/android_natives.h>
+
 namespace android {
 
 // ---------------------------------------------------------------------------
 
+class BufferMapper;
 class Rect;
+class Surface;
 class SurfaceComposerClient;
+struct per_client_cblk_t;
+struct layer_cblk_t;
 
-class Surface : public RefBase
+// ---------------------------------------------------------------------------
+
+class SurfaceControl : public RefBase
 {
-
 public:
-    struct SurfaceInfo {
-        uint32_t    w;
-        uint32_t    h;
-        uint32_t    bpr;
-        PixelFormat format;
-        void*       bits;
-        void*       base;
-        uint32_t    reserved[2];
-    };
-
-    bool        isValid() const { return this && mToken>=0 && mClient!=0; }
+    static bool isValid(const sp<SurfaceControl>& surface) {
+        return (surface != 0) && surface->isValid();
+    }
+    bool isValid() {
+        return mToken>=0 && mClient!=0;
+    }
+    static bool isSameSurface(
+            const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
+        
     SurfaceID   ID() const      { return mToken; }
-
-    status_t    lock(SurfaceInfo* info, bool blocking = true);
-    status_t    lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
-    status_t    unlockAndPost();
-    status_t    unlock();
-
-    void*       heapBase(int i) const;
     uint32_t    getFlags() const { return mFlags; }
+    uint32_t    getIdentity() const { return mIdentity; }
 
-    // setSwapRectangle() is mainly used by EGL
-    void        setSwapRectangle(const Rect& r);
-    const Rect& swapRectangle() const;
-    status_t    nextBuffer(SurfaceInfo* info);
-
-    sp<Surface>         dup() const;
-    static sp<Surface>  readFromParcel(Parcel* parcel);
-    static status_t     writeToParcel(const sp<Surface>& surface, Parcel* parcel);
-    static bool         isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs);
-
+    // release surface data from java
+    void        clear();
+    
     status_t    setLayer(int32_t layer);
     status_t    setPosition(int32_t x, int32_t y);
     status_t    setSize(uint32_t w, uint32_t h);
@@ -83,8 +75,17 @@
     status_t    setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
     status_t    setFreezeTint(uint32_t tint);
 
-    uint32_t    getIdentity() const { return mIdentity; }
+    static status_t writeSurfaceToParcel(
+            const sp<SurfaceControl>& control, Parcel* parcel);
+
+    sp<Surface> getSurface() const;
+
 private:
+    // can't be copied
+    SurfaceControl& operator = (SurfaceControl& rhs);
+    SurfaceControl(const SurfaceControl& rhs);
+
+    
     friend class SurfaceComposerClient;
 
     // camera and camcorder need access to the ISurface binder interface for preview
@@ -92,43 +93,130 @@
     friend class MediaRecorder;
     // mediaplayer needs access to ISurface for display
     friend class MediaPlayer;
+    // for testing
+    friend class Test;
+    const sp<ISurface>& getISurface() const { return mSurface; }
+    
+
+    friend class Surface;
+
+    SurfaceControl(
+            const sp<SurfaceComposerClient>& client,
+            const sp<ISurface>& surface,
+            const ISurfaceFlingerClient::surface_data_t& data,
+            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+
+    ~SurfaceControl();
+
+    status_t validate(per_client_cblk_t const* cblk) const;
+    void destroy();
+    
+    sp<SurfaceComposerClient>   mClient;
+    sp<ISurface>                mSurface;
+    SurfaceID                   mToken;
+    uint32_t                    mIdentity;
+    PixelFormat                 mFormat;
+    uint32_t                    mFlags;
+    mutable Mutex               mLock;
+    
+    mutable sp<Surface>         mSurfaceData;
+};
+    
+// ---------------------------------------------------------------------------
+
+class Surface 
+    : public EGLNativeBase<android_native_window_t, Surface, RefBase>
+{
+public:
+    struct SurfaceInfo {
+        uint32_t    w;
+        uint32_t    h;
+        uint32_t    s;
+        uint32_t    usage;
+        PixelFormat format;
+        void*       bits;
+        uint32_t    reserved[2];
+    };
+
+    Surface(const Parcel& data);
+
+    static bool isValid(const sp<Surface>& surface) {
+        return (surface != 0) && surface->isValid();
+    }
+    bool isValid() {
+        return mToken>=0 && mClient!=0;
+    }
+    static bool isSameSurface(
+            const sp<Surface>& lhs, const sp<Surface>& rhs);
+    SurfaceID   ID() const      { return mToken; }
+    uint32_t    getFlags() const { return mFlags; }
+    uint32_t    getIdentity() const { return mIdentity; }
+
+
+    status_t    lock(SurfaceInfo* info, bool blocking = true);
+    status_t    lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
+    status_t    unlockAndPost();
+
+    // setSwapRectangle() is intended to be used by GL ES clients
+    void        setSwapRectangle(const Rect& r);
+
+private:
+    // can't be copied
+    Surface& operator = (Surface& rhs);
+    Surface(const Surface& rhs);
+
+    Surface(const sp<SurfaceControl>& control);
+    void init();
+     ~Surface();
+  
+    friend class SurfaceComposerClient;
+    friend class SurfaceControl;
+
+    // camera and camcorder need access to the ISurface binder interface for preview
+    friend class Camera;
+    friend class MediaRecorder;
+    // mediaplayer needs access to ISurface for display
+    friend class MediaPlayer;
     friend class Test;
     const sp<ISurface>& getISurface() const { return mSurface; }
 
-    // can't be copied
-    Surface& operator = (Surface& rhs);
-    Surface(const Surface& rhs);
+    status_t getBufferLocked(int index);
+   
+           status_t validate(per_client_cblk_t const* cblk) const;
+    static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty);
 
-    Surface(const sp<SurfaceComposerClient>& client,
-            const sp<ISurface>& surface,
-            const ISurfaceFlingerClient::surface_data_t& data,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
-            bool owner = true);
+    inline const BufferMapper& getBufferMapper() const { return mBufferMapper; }
+    inline BufferMapper& getBufferMapper() { return mBufferMapper; }
+    
+    static int setSwapInterval(android_native_window_t* window, int interval);
+    static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
+    static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+    static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
 
-    Surface(Surface const* rhs);
+    int dequeueBuffer(android_native_buffer_t** buffer);
+    int lockBuffer(android_native_buffer_t* buffer);
+    int queueBuffer(android_native_buffer_t* buffer);
 
-    ~Surface();
+    status_t dequeueBuffer(sp<SurfaceBuffer>* buffer);
+    status_t lockBuffer(const sp<SurfaceBuffer>& buffer);
+    status_t queueBuffer(const sp<SurfaceBuffer>& buffer);
 
-    Region dirtyRegion() const;
-    void setDirtyRegion(const Region& region) const;
-
-    // this locks protects calls to lockSurface() / unlockSurface()
-    // and is called by SurfaceComposerClient.
-    Mutex& getLock() const { return mSurfaceLock; }
-
+    
+    alloc_device_t*             mAllocDevice;
     sp<SurfaceComposerClient>   mClient;
     sp<ISurface>                mSurface;
-    sp<IMemoryHeap>             mHeap[2];
+    sp<SurfaceBuffer>           mBuffers[2];
+    sp<SurfaceBuffer>           mLockedBuffer;
     SurfaceID                   mToken;
     uint32_t                    mIdentity;
     PixelFormat                 mFormat;
     uint32_t                    mFlags;
-    const bool                  mOwner;
-    mutable void*               mSurfaceHeapBase[2];
     mutable Region              mDirtyRegion;
-    mutable Rect                mSwapRectangle;
+    mutable Region              mOldDirtyRegion;
     mutable uint8_t             mBackbufferIndex;
     mutable Mutex               mSurfaceLock;
+    Rect                        mSwapRectangle;
+    BufferMapper&               mBufferMapper;
 };
 
 }; // namespace android
diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h
index 76a3b55..2a35256 100644
--- a/include/ui/SurfaceComposerClient.h
+++ b/include/ui/SurfaceComposerClient.h
@@ -62,7 +62,7 @@
     // surface creation / destruction
 
     //! Create a surface
-    sp<Surface>   createSurface(
+    sp<SurfaceControl> createSurface(
             int pid,            //!< pid of the process the surfacec is for
             DisplayID display,  //!< Display to create this surface on
             uint32_t w,         //!< width in pixel
@@ -111,51 +111,35 @@
 
 private:
     friend class Surface;
+    friend class SurfaceControl;
     
     SurfaceComposerClient(const sp<ISurfaceComposer>& sm, 
             const sp<IBinder>& conn);
 
-    status_t    hide(Surface* surface);
-    status_t    show(Surface* surface, int32_t layer = -1);
-    status_t    freeze(Surface* surface);
-    status_t    unfreeze(Surface* surface);
-    status_t    setFlags(Surface* surface, uint32_t flags, uint32_t mask);
-    status_t    setTransparentRegionHint(Surface* surface, const Region& transparent);
-    status_t    setLayer(Surface* surface, int32_t layer);
-    status_t    setAlpha(Surface* surface, float alpha=1.0f);
-    status_t    setFreezeTint(Surface* surface, uint32_t tint);
-    status_t    setMatrix(Surface* surface, float dsdx, float dtdx, float dsdy, float dtdy);
-    status_t    setPosition(Surface* surface, int32_t x, int32_t y);
-    status_t    setSize(Surface* surface, uint32_t w, uint32_t h);
+    status_t    hide(SurfaceID id);
+    status_t    show(SurfaceID id, int32_t layer = -1);
+    status_t    freeze(SurfaceID id);
+    status_t    unfreeze(SurfaceID id);
+    status_t    setFlags(SurfaceID id, uint32_t flags, uint32_t mask);
+    status_t    setTransparentRegionHint(SurfaceID id, const Region& transparent);
+    status_t    setLayer(SurfaceID id, int32_t layer);
+    status_t    setAlpha(SurfaceID id, float alpha=1.0f);
+    status_t    setFreezeTint(SurfaceID id, uint32_t tint);
+    status_t    setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy);
+    status_t    setPosition(SurfaceID id, int32_t x, int32_t y);
+    status_t    setSize(SurfaceID id, uint32_t w, uint32_t h);
     
-    //! Unlock the surface, and specify the dirty region if any
-    status_t    unlockAndPostSurface(Surface* surface);
-    status_t    unlockSurface(Surface* surface);
-
-    status_t    lockSurface(Surface* surface,
-                            Surface::SurfaceInfo* info,
-                            Region* dirty,
-                            bool blocking = true);
-
-    status_t    nextBuffer(Surface* surface,
-                            Surface::SurfaceInfo* info);
+    void        signalServer();
 
     status_t    destroySurface(SurfaceID sid);
 
     void        _init(const sp<ISurfaceComposer>& sm,
                     const sp<ISurfaceFlingerClient>& conn);
-    void        _signal_server();
-    static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty);
 
-    inline layer_state_t*   _get_state_l(const sp<Surface>& surface);
-    layer_state_t*          _lockLayerState(const sp<Surface>& surface);
+    inline layer_state_t*   _get_state_l(SurfaceID id);
+    layer_state_t*          _lockLayerState(SurfaceID id);
     inline void             _unlockLayerState();
 
-    status_t validateSurface(
-            per_client_cblk_t const* cblk, Surface const * surface);
-
-    void pinHeap(const sp<IMemoryHeap>& heap);
-
     mutable     Mutex                               mLock;
                 layer_state_t*                      mPrebuiltLayerState;
                 SortedVector<layer_state_t>         mStates;
@@ -167,9 +151,6 @@
                 per_client_cblk_t*          mControl;
                 sp<IMemory>                 mControlMemory;
                 sp<ISurfaceFlingerClient>   mClient;
-                sp<IMemoryHeap>             mSurfaceHeap;
-                uint8_t*                    mSurfaceHeapBase;
-                void*                       mGL;
                 SurfaceFlingerSynchro*      mSignalServer;
 };
 
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
new file mode 100644
index 0000000..0398ea7
--- /dev/null
+++ b/include/ui/egl/android_natives.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_ANDROID_NATIVES_H
+#define ANDROID_ANDROID_NATIVES_H
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <hardware/gralloc.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;
+
+// ---------------------------------------------------------------------------
+
+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);
+};
+
+// ---------------------------------------------------------------------------
+
+struct android_native_window_t 
+{
+#ifdef __cplusplus
+    android_native_window_t()
+        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
+    {
+        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
+        common.version = sizeof(android_native_window_t);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+#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 android_native_window_t* 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 android_native_window_t* 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 android_native_window_t* 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 android_native_window_t* window,
+                struct android_native_buffer_t* buffer);
+
+    
+    void* reserved_proc[5];
+};
+
+// ---------------------------------------------------------------------------
+
+/* FIXME: this is legacy for pixmaps */
+struct egl_native_pixmap_t
+{
+    int32_t     version;    /* must be 32 */
+    int32_t     width;
+    int32_t     height;
+    int32_t     stride;
+    uint8_t*    data;
+    uint8_t     format;
+    uint8_t     rfu[3];
+    union {
+        uint32_t    compressedFormat;
+        int32_t     vstride;
+    };
+    int32_t     reserved;
+};
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/*
+ * This helper class turns an EGL android_native_xxx type into a C++
+ * reference-counted object; with proper type conversions.
+ */
+template <typename NATIVE_TYPE, typename TYPE, typename REF>
+class EGLNativeBase : public NATIVE_TYPE, public REF
+{
+protected:
+    typedef EGLNativeBase<NATIVE_TYPE, TYPE, REF> BASE;
+    EGLNativeBase() : NATIVE_TYPE(), REF() {
+        NATIVE_TYPE::common.incRef = incRef;
+        NATIVE_TYPE::common.decRef = decRef;
+    }
+    static inline TYPE* getSelf(NATIVE_TYPE* self) {
+        return static_cast<TYPE*>(self);
+    }
+    static inline TYPE const* getSelf(NATIVE_TYPE const* self) {
+        return static_cast<TYPE const *>(self);
+    }
+    static inline TYPE* getSelf(android_native_base_t* base) {
+        return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));
+    }
+    static inline TYPE const * getSelf(android_native_base_t const* base) {
+        return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));
+    }
+    static void incRef(android_native_base_t* base) {
+        EGLNativeBase* self = getSelf(base);
+        self->incStrong(self);
+    }
+    static void decRef(android_native_base_t* base) {
+        EGLNativeBase* self = getSelf(base);
+        self->decStrong(self);
+    }
+};
+
+} // namespace android
+#endif // __cplusplus
+
+/*****************************************************************************/
+
+#endif /* ANDROID_ANDROID_NATIVES_H */
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
index a662b9c..21d04bd 100644
--- a/include/utils/Debug.h
+++ b/include/utils/Debug.h
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-//
-// Debugging tools.  These should be able to be stripped
-// in release builds.
-//
 #ifndef ANDROID_DEBUG_H
 #define ANDROID_DEBUG_H
 
@@ -25,9 +21,30 @@
 #include <sys/types.h>
 
 namespace android {
+// ---------------------------------------------------------------------------
 
+#ifdef __cplusplus
 template<bool> struct CompileTimeAssert;
 template<> struct CompileTimeAssert<true> {};
+#define COMPILE_TIME_ASSERT(_exp) \
+    template class CompileTimeAssert< (_exp) >;
+#endif
+
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+template<bool C, typename LSH, typename RHS> struct CompileTimeIfElse;
+template<typename LHS, typename RHS> 
+struct CompileTimeIfElse<true,  LHS, RHS> { typedef LHS TYPE; };
+template<typename LHS, typename RHS> 
+struct CompileTimeIfElse<false, LHS, RHS> { typedef RHS TYPE; };
+#endif
+
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 const char* stringForIndent(int32_t indentLevel);
 
@@ -35,11 +52,17 @@
 
 void printTypeCode(uint32_t typeCode,
     debugPrintFunc func = 0, void* cookie = 0);
+
 void printHexData(int32_t indent, const void *buf, size_t length,
     size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
     size_t alignment=0, bool cArrayStyle=false,
     debugPrintFunc func = 0, void* cookie = 0);
 
+#ifdef __cplusplus
+}
+#endif
+
+// ---------------------------------------------------------------------------
 }; // namespace android
 
 #endif // ANDROID_DEBUG_H
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h
index f4513ee..6bcdea4 100644
--- a/include/utils/KeyedVector.h
+++ b/include/utils/KeyedVector.h
@@ -164,7 +164,7 @@
 template<typename KEY, typename VALUE> inline
 ssize_t KeyedVector<KEY,VALUE>::replaceValueAt(size_t index, const VALUE& item) {
     if (index<size()) {
-        mVector.editValueAt(index).value = item;
+        mVector.editItemAt(index).value = item;
         return index;
     }
     return BAD_INDEX;
diff --git a/include/utils/List.h b/include/utils/List.h
index 1a6be9a..4041a89 100644
--- a/include/utils/List.h
+++ b/include/utils/List.h
@@ -22,147 +22,200 @@
 // construction, so if the compiler's auto-generated versions won't work for
 // you, define your own.
 //
-// The only class you want to use from here is "List".  Do not use classes
-// starting with "_" directly.
+// The only class you want to use from here is "List".
 //
 #ifndef _LIBS_UTILS_LIST_H
 #define _LIBS_UTILS_LIST_H
 
+#include <stddef.h>
+#include <stdint.h>
+
 namespace android {
 
 /*
- * One element in the list.
- */
-template<class T> class _ListNode {
-public:
-    typedef _ListNode<T> _Node;
-
-    _ListNode(const T& val) : mVal(val) {}
-    ~_ListNode(void) {}
-
-    T& getRef(void) { return mVal; }
-    void setVal(const T& val) { mVal = val; }
-
-    _Node* getPrev(void) const { return mpPrev; }
-    void setPrev(_Node* ptr) { mpPrev = ptr; }
-    _Node* getNext(void) const { return mpNext; }
-    void setNext(_Node* ptr) { mpNext = ptr; }
-
-private:
-    T           mVal;
-    _Node*      mpPrev;
-    _Node*      mpNext;
-};
-
-/*
- * Iterator for walking through the list.
- */
-template<class T, class Tref> class _ListIterator {
-public:
-    typedef _ListIterator<T,Tref> _Iter;
-    typedef _ListNode<T> _Node;
-
-    _ListIterator(void) {}
-    _ListIterator(_Node* ptr) : mpNode(ptr) {}
-    ~_ListIterator(void) {}
-
-    /*
-     * Dereference operator.  Used to get at the juicy insides.
-     */
-    Tref operator*() const { return mpNode->getRef(); }
-
-    /*
-     * Iterator comparison.
-     */
-    bool operator==(const _Iter& right) const { return mpNode == right.mpNode; }
-    bool operator!=(const _Iter& right) const { return mpNode != right.mpNode; }
-
-    /*
-     * Incr/decr, used to move through the list.
-     */
-    _Iter& operator++(void) {        // pre-increment
-        mpNode = mpNode->getNext();
-        return *this;
-    }
-    _Iter operator++(int) {          // post-increment
-        _Iter tmp = *this;
-        ++*this;
-        return tmp;
-    }
-    _Iter& operator--(void) {        // pre-increment
-        mpNode = mpNode->getPrev();
-        return *this;
-    }
-    _Iter operator--(int) {          // post-increment
-        _Iter tmp = *this;
-        --*this;
-        return tmp;
-    }
-
-    _Node* getNode(void) const { return mpNode; }
-
-private:
-    _Node*      mpNode;
-};
-
-
-/*
  * Doubly-linked list.  Instantiate with "List<MyClass> myList".
  *
  * Objects added to the list are copied using the assignment operator,
  * so this must be defined.
  */
-template<class T> class List {
-public:
-    typedef _ListNode<T> _Node;
+template<typename T> 
+class List 
+{
+protected:
+    /*
+     * One element in the list.
+     */
+    class _Node {
+    public:
+        explicit _Node(const T& val) : mVal(val) {}
+        ~_Node() {}
+        inline T& getRef() { return mVal; }
+        inline const T& getRef() const { return mVal; }
+        inline _Node* getPrev() const { return mpPrev; }
+        inline _Node* getNext() const { return mpNext; }
+        inline void setVal(const T& val) { mVal = val; }
+        inline void setPrev(_Node* ptr) { mpPrev = ptr; }
+        inline void setNext(_Node* ptr) { mpNext = ptr; }
+    private:
+        friend class List;
+        friend class _ListIterator;
+        T           mVal;
+        _Node*      mpPrev;
+        _Node*      mpNext;
+    };
 
-    List(void) {
+    /*
+     * Iterator for walking through the list.
+     */
+    
+    template <typename TYPE>
+    struct CONST_ITERATOR {
+        typedef _Node const * NodePtr;
+        typedef const TYPE Type;
+    };
+    
+    template <typename TYPE>
+    struct NON_CONST_ITERATOR {
+        typedef _Node* NodePtr;
+        typedef TYPE Type;
+    };
+    
+    template<
+        typename U,
+        template <class> class Constness
+    > 
+    class _ListIterator {
+        typedef _ListIterator<U, Constness>     _Iter;
+        typedef typename Constness<U>::NodePtr  _NodePtr;
+        typedef typename Constness<U>::Type     _Type;
+
+        explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
+
+    public:
+        _ListIterator() {}
+        _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
+        ~_ListIterator() {}
+        
+        // this will handle conversions from iterator to const_iterator
+        // (and also all convertible iterators)
+        // Here, in this implementation, the iterators can be converted
+        // if the nodes can be converted
+        template<typename V> explicit 
+        _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
+        
+
+        /*
+         * Dereference operator.  Used to get at the juicy insides.
+         */
+        _Type& operator*() const { return mpNode->getRef(); }
+        _Type* operator->() const { return &(mpNode->getRef()); }
+
+        /*
+         * Iterator comparison.
+         */
+        inline bool operator==(const _Iter& right) const { 
+            return mpNode == right.mpNode; }
+        
+        inline bool operator!=(const _Iter& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * handle comparisons between iterator and const_iterator
+         */
+        template<typename OTHER>
+        inline bool operator==(const OTHER& right) const { 
+            return mpNode == right.mpNode; }
+        
+        template<typename OTHER>
+        inline bool operator!=(const OTHER& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * Incr/decr, used to move through the list.
+         */
+        inline _Iter& operator++() {     // pre-increment
+            mpNode = mpNode->getNext();
+            return *this;
+        }
+        const _Iter operator++(int) {    // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getNext();
+            return tmp;
+        }
+        inline _Iter& operator--() {     // pre-increment
+            mpNode = mpNode->getPrev();
+            return *this;
+        }
+        const _Iter operator--(int) {   // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getPrev();
+            return tmp;
+        }
+
+        inline _NodePtr getNode() const { return mpNode; }
+
+    private:
+        friend class List;
+        _NodePtr mpNode;
+    };
+
+public:
+    List() {
         prep();
     }
     List(const List<T>& src) {      // copy-constructor
         prep();
         insert(begin(), src.begin(), src.end());
     }
-    virtual ~List(void) {
+    virtual ~List() {
         clear();
         delete[] (unsigned char*) mpMiddle;
     }
 
-    typedef _ListIterator<T,T&> iterator;
-    typedef _ListIterator<T, const T&> const_iterator;
+    typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
+    typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
 
     List<T>& operator=(const List<T>& right);
 
     /* returns true if the list is empty */
-    bool empty(void) const { return mpMiddle->getNext() == mpMiddle; }
+    inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
 
     /* return #of elements in list */
-    unsigned int size(void) const {
-        return distance(begin(), end());
+    size_t size() const {
+        return size_t(distance(begin(), end()));
     }
 
     /*
      * Return the first element or one past the last element.  The
-     * _ListNode* we're returning is converted to an "iterator" by a
+     * _Node* we're returning is converted to an "iterator" by a
      * constructor in _ListIterator.
      */
-    iterator begin()                { return mpMiddle->getNext(); }
-    const_iterator begin() const    { return mpMiddle->getNext(); }
-    iterator end()                  { return mpMiddle; }
-    const_iterator end() const      { return mpMiddle; }
+    inline iterator begin() { 
+        return iterator(mpMiddle->getNext()); 
+    }
+    inline const_iterator begin() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle->getNext())); 
+    }
+    inline iterator end() { 
+        return iterator(mpMiddle); 
+    }
+    inline const_iterator end() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle)); 
+    }
 
     /* add the object to the head or tail of the list */
     void push_front(const T& val) { insert(begin(), val); }
     void push_back(const T& val) { insert(end(), val); }
 
     /* insert before the current node; returns iterator at new node */
-    iterator insert(iterator posn, const T& val) {
+    iterator insert(iterator posn, const T& val) 
+    {
         _Node* newNode = new _Node(val);        // alloc & copy-construct
         newNode->setNext(posn.getNode());
         newNode->setPrev(posn.getNode()->getPrev());
         posn.getNode()->getPrev()->setNext(newNode);
         posn.getNode()->setPrev(newNode);
-        return newNode;
+        return iterator(newNode);
     }
 
     /* insert a range of elements before the current node */
@@ -178,18 +231,18 @@
         pPrev->setNext(pNext);
         pNext->setPrev(pPrev);
         delete posn.getNode();
-        return pNext;
+        return iterator(pNext);
     }
 
     /* remove a range of elements */
     iterator erase(iterator first, iterator last) {
         while (first != last)
             erase(first++);     // don't erase than incr later!
-        return last;
+        return iterator(last);
     }
 
     /* remove all contents of the list */
-    void clear(void) {
+    void clear() {
         _Node* pCurrent = mpMiddle->getNext();
         _Node* pNext;
 
@@ -207,21 +260,20 @@
      * will be equal to "last".  The iterators must refer to the same
      * list.
      *
-     * (This is actually a generic iterator function.  It should be part
-     * of some other class, possibly an iterator base class.  It needs to
-     * know the difference between a list, which has to march through,
-     * and a vector, which can just do pointer math.)
+     * FIXME: This is actually a generic iterator function. It should be a 
+     * template function at the top-level with specializations for things like
+     * vector<>, which can just do pointer math). Here we limit it to
+     * _ListIterator of the same type but different constness.
      */
-    unsigned int distance(iterator first, iterator last) {
-        unsigned int count = 0;
-        while (first != last) {
-            ++first;
-            ++count;
-        }
-        return count;
-    }
-    unsigned int distance(const_iterator first, const_iterator last) const {
-        unsigned int count = 0;
+    template<
+        typename U,
+        template <class> class CL,
+        template <class> class CR
+    > 
+    ptrdiff_t distance(
+            _ListIterator<U, CL> first, _ListIterator<U, CR> last) const 
+    {
+        ptrdiff_t count = 0;
         while (first != last) {
             ++first;
             ++count;
@@ -231,12 +283,12 @@
 
 private:
     /*
-     * I want a _ListNode but don't need it to hold valid data.  More
+     * I want a _Node but don't need it to hold valid data.  More
      * to the point, I don't want T's constructor to fire, since it
      * might have side-effects or require arguments.  So, we do this
      * slightly uncouth storage alloc.
      */
-    void prep(void) {
+    void prep() {
         mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
         mpMiddle->setPrev(mpMiddle);
         mpMiddle->setNext(mpMiddle);
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index cbda0fd..bd7f28c 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -156,6 +156,10 @@
             delete static_cast<const T*>(this);
         }
     }
+    //! DEBUGGING ONLY: Get current strong ref count.
+    inline int32_t getStrongCount() const {
+        return mCount;
+    }
     
 protected:
     inline ~LightRefBase() { }
diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h
new file mode 100644
index 0000000..bc7626a8
--- /dev/null
+++ b/include/utils/Singleton.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UTILS_SINGLETON_H
+#define ANDROID_UTILS_SINGLETON_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+template <typename TYPE>
+class Singleton
+{
+public:
+    static TYPE& getInstance() {
+        Mutex::Autolock _l(sLock);
+        TYPE* instance = sInstance;
+        if (instance == 0) {
+            instance = new TYPE();
+            sInstance = instance;
+        }
+        return *instance;
+    }
+    
+protected:
+    ~Singleton() { };
+    Singleton() { };
+
+private:
+    Singleton(const Singleton&);
+    Singleton& operator = (const Singleton&);
+    static Mutex sLock;
+    static TYPE* sInstance;
+};
+
+/*
+ * use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
+ * (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
+ * and avoid to have a copy of them in each compilation units Singleton<TYPE>
+ * is used.
+ */
+
+#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE)             \
+    template class Singleton< TYPE >;                       \
+    template< class TYPE > Mutex Singleton< TYPE >::sLock;  \
+    template<> TYPE* Singleton< TYPE >::sInstance(0);
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_UTILS_SINGLETON_H
+
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index a5698f2..16936e3 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -5,23 +5,21 @@
     clz.cpp.arm \
     DisplayHardware/DisplayHardware.cpp \
     DisplayHardware/DisplayHardwareBase.cpp \
-    GPUHardware/GPUHardware.cpp \
     BlurFilter.cpp.arm \
-    CPUGauge.cpp \
+    BufferAllocator.cpp \
     Layer.cpp \
     LayerBase.cpp \
     LayerBuffer.cpp \
     LayerBlur.cpp \
     LayerBitmap.cpp \
     LayerDim.cpp \
-    LayerOrientationAnim.cpp \
-    LayerOrientationAnimRotate.cpp \
-    OrientationAnimation.cpp \
+    MessageQueue.cpp \
     SurfaceFlinger.cpp \
     Tokenizer.cpp \
-    Transform.cpp \
-    VRamHeap.cpp
+    Transform.cpp
 
+LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 # need "-lrt" on Linux simulator to pick up clock_gettime
 ifeq ($(TARGET_SIMULATOR),true)
diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/surfaceflinger/BufferAllocator.cpp
new file mode 100644
index 0000000..cee8b64
--- /dev/null
+++ b/libs/surfaceflinger/BufferAllocator.cpp
@@ -0,0 +1,118 @@
+/* 
+**
+** 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 <sys/mman.h>
+#include <cutils/ashmem.h>
+#include <cutils/log.h>
+
+#include <utils/Singleton.h>
+#include <utils/String8.h>
+
+#include "BufferAllocator.h"
+
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE( BufferAllocator )
+
+Mutex BufferAllocator::sLock;
+KeyedVector<buffer_handle_t, BufferAllocator::alloc_rec_t> BufferAllocator::sAllocList;
+
+BufferAllocator::BufferAllocator()
+    : mAllocDev(0)
+{
+    hw_module_t const* module;
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+    if (err == 0) {
+        gralloc_open(module, &mAllocDev);
+    }
+}
+
+BufferAllocator::~BufferAllocator()
+{
+    gralloc_close(mAllocDev);
+}
+
+void BufferAllocator::dump(String8& result) const
+{
+    Mutex::Autolock _l(sLock);
+    KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+    size_t total = 0;
+    const size_t SIZE = 512;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "Allocated buffers:\n");
+    result.append(buffer);
+    const size_t c = list.size();
+    for (size_t i=0 ; i<c ; i++) {
+        const alloc_rec_t& rec(list.valueAt(i));
+        snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u x %4u | %2d | 0x%08x\n",
+            list.keyAt(i), rec.size/1024.0f, 
+            rec.w, rec.h, rec.format, rec.usage);
+        result.append(buffer);
+        total += rec.size;
+    }
+    snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f);
+    result.append(buffer);
+}
+
+status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
+        int usage, buffer_handle_t* handle, int32_t* stride)
+{
+    Mutex::Autolock _l(mLock);
+    
+    // we have a h/w allocator and h/w buffer is requested
+    status_t err = mAllocDev->alloc(mAllocDev,
+            w, h, format, usage, handle, stride);
+    LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
+            w, h, format, usage, err, strerror(-err));
+    
+    if (err == NO_ERROR) {
+        Mutex::Autolock _l(sLock);
+        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+        alloc_rec_t rec;
+        rec.w = w;
+        rec.h = h;
+        rec.format = format;
+        rec.usage = usage;
+        rec.vaddr = 0;
+        rec.size = h * stride[0] * bytesPerPixel(format);
+        list.add(*handle, rec);
+    }
+
+    return err;
+}
+
+status_t BufferAllocator::free(buffer_handle_t handle)
+{
+    Mutex::Autolock _l(mLock);
+
+    status_t err = mAllocDev->free(mAllocDev, handle);
+    LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
+    
+    if (err == NO_ERROR) {
+        Mutex::Autolock _l(sLock);
+        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+        list.removeItem(handle);
+    }
+
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/surfaceflinger/BufferAllocator.h b/libs/surfaceflinger/BufferAllocator.h
new file mode 100644
index 0000000..a279ded
--- /dev/null
+++ b/libs/surfaceflinger/BufferAllocator.h
@@ -0,0 +1,96 @@
+/* 
+**
+** 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.
+*/
+
+#ifndef ANDROID_BUFFER_ALLOCATOR_H
+#define ANDROID_BUFFER_ALLOCATOR_H
+
+#include <stdint.h>
+
+#include <cutils/native_handle.h>
+
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/Singleton.h>
+
+#include <ui/PixelFormat.h>
+
+#include <hardware/gralloc.h>
+
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class String8;
+
+class BufferAllocator : public Singleton<BufferAllocator>
+{
+public:
+    enum {
+        USAGE_SW_READ_NEVER     = GRALLOC_USAGE_SW_READ_NEVER,
+        USAGE_SW_READ_RARELY    = GRALLOC_USAGE_SW_READ_RARELY,
+        USAGE_SW_READ_OFTEN     = GRALLOC_USAGE_SW_READ_OFTEN,
+        USAGE_SW_READ_MASK      = GRALLOC_USAGE_SW_READ_MASK,
+        
+        USAGE_SW_WRITE_NEVER    = GRALLOC_USAGE_SW_WRITE_NEVER,
+        USAGE_SW_WRITE_RARELY   = GRALLOC_USAGE_SW_WRITE_RARELY,
+        USAGE_SW_WRITE_OFTEN    = GRALLOC_USAGE_SW_WRITE_OFTEN,
+        USAGE_SW_WRITE_MASK     = GRALLOC_USAGE_SW_WRITE_MASK,
+        
+        USAGE_SOFTWARE_MASK     = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,
+        
+        USAGE_HW_TEXTURE        = GRALLOC_USAGE_HW_TEXTURE,
+        USAGE_HW_RENDER         = GRALLOC_USAGE_HW_RENDER,
+        USAGE_HW_2D             = GRALLOC_USAGE_HW_2D,
+        USAGE_HW_MASK           = GRALLOC_USAGE_HW_MASK
+    };
+
+    static inline BufferAllocator& get() { return getInstance(); }
+    
+
+    status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage,
+            buffer_handle_t* handle, int32_t* stride);
+
+    status_t free(buffer_handle_t handle);
+
+    void dump(String8& res) const;
+
+private:
+    struct alloc_rec_t {
+        uint32_t w;
+        uint32_t h;
+        PixelFormat format;
+        uint32_t usage;
+        void* vaddr;
+        size_t size;
+    };
+    
+    static Mutex sLock;
+    static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;
+    
+    friend class Singleton<BufferAllocator>;
+    BufferAllocator();
+    ~BufferAllocator();
+    
+    mutable Mutex mLock;
+    alloc_device_t  *mAllocDev;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_BUFFER_ALLOCATOR_H
diff --git a/libs/surfaceflinger/CPUGauge.cpp b/libs/surfaceflinger/CPUGauge.cpp
deleted file mode 100644
index 74a9270..0000000
--- a/libs/surfaceflinger/CPUGauge.cpp
+++ /dev/null
@@ -1,171 +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.
- */
-
-#define LOG_TAG "CPUGauge"
-
-#include <stdint.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <math.h>
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <ui/PixelFormat.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <ui/DisplayInfo.h>
-#include <ui/ISurfaceComposer.h>
-#include <ui/ISurfaceFlingerClient.h>
-
-#include <pixelflinger/pixelflinger.h>
-
-#include "CPUGauge.h"
-
-namespace android {
-
-CPUGauge::CPUGauge( const sp<ISurfaceComposer>& composer,
-                    nsecs_t interval,
-                    int clock,
-                    int refclock)
-    :   Thread(false), 
-        mInterval(interval), mClock(clock), mRefClock(refclock),
-        mReferenceTime(0),
-        mReferenceWorkingTime(0), mCpuUsage(0),
-        mRefIdleTime(0), mIdleTime(0)
-{
-    mFd = fopen("/proc/stat", "r");
-    setvbuf(mFd, NULL, _IONBF, 0);
-
-    mSession = SurfaceComposerClient::clientForConnection(
-        composer->createConnection()->asBinder());
-}
-
-CPUGauge::~CPUGauge()
-{
-    fclose(mFd);
-}
-
-const sp<SurfaceComposerClient>& CPUGauge::session() const 
-{
-    return mSession;
-}
-
-void CPUGauge::onFirstRef()
-{
-    run("CPU Gauge");
-}
-
-status_t CPUGauge::readyToRun()
-{
-    LOGI("Starting CPU gauge...");
-    return NO_ERROR;
-}
-
-bool CPUGauge::threadLoop()
-{
-    DisplayInfo dinfo;
-    session()->getDisplayInfo(0, &dinfo);
-    sp<Surface> s(session()->createSurface(getpid(), 0, dinfo.w, 4, PIXEL_FORMAT_OPAQUE));
-    session()->openTransaction();
-    s->setLayer(INT_MAX);
-    session()->closeTransaction();
-    
-    static const GGLfixed colors[4][4] = {
-            { 0x00000, 0x10000, 0x00000, 0x10000 },
-            { 0x10000, 0x10000, 0x00000, 0x10000 },
-            { 0x10000, 0x00000, 0x00000, 0x10000 },
-            { 0x00000, 0x00000, 0x00000, 0x10000 },
-        };
-
-    GGLContext* gl;
-    gglInit(&gl);
-    gl->activeTexture(gl, 0);
-    gl->disable(gl, GGL_TEXTURE_2D);
-    gl->disable(gl, GGL_BLEND);
-
-    const int w = dinfo.w;
-
-    while(!exitPending())
-    {
-        mLock.lock();
-            const float cpuUsage = this->cpuUsage();
-            const float totalCpuUsage = 1.0f - idle();
-        mLock.unlock();
-
-        Surface::SurfaceInfo info;
-        s->lock(&info);
-            GGLSurface fb;
-                fb.version = sizeof(GGLSurface);
-                fb.width   = info.w;
-                fb.height  = info.h;
-                fb.stride  = info.w;
-                fb.format  = info.format;
-                fb.data = (GGLubyte*)info.bits;
-
-            gl->colorBuffer(gl, &fb);
-            gl->color4xv(gl, colors[3]);
-            gl->recti(gl, 0, 0, w, 4);
-            gl->color4xv(gl, colors[2]); // red
-            gl->recti(gl, 0, 0, int(totalCpuUsage*w), 2);
-            gl->color4xv(gl, colors[0]); // green
-            gl->recti(gl, 0, 2, int(cpuUsage*w), 4);
-        
-        s->unlockAndPost(); 
-
-        usleep(ns2us(mInterval));
-    }
-
-    gglUninit(gl);
-    return false;
-}
-
-void CPUGauge::sample()
-{
-    if (mLock.tryLock() == NO_ERROR) {
-        const nsecs_t now = systemTime(mRefClock);
-        const nsecs_t referenceTime = now-mReferenceTime;
-        if (referenceTime >= mInterval) {
-            const float reftime = 1.0f / referenceTime;
-            const nsecs_t nowWorkingTime = systemTime(mClock);
-            
-            char buf[256];
-            fgets(buf, 256, mFd);
-            rewind(mFd);
-            char *str = buf+5;
-            char const * const usermode = strsep(&str, " ");  (void)usermode;
-            char const * const usernice = strsep(&str, " ");  (void)usernice;
-            char const * const systemmode = strsep(&str, " ");(void)systemmode;
-            char const * const idle = strsep(&str, " ");
-            const nsecs_t nowIdleTime = atoi(idle) * 10000000LL;
-            mIdleTime = float(nowIdleTime - mRefIdleTime) * reftime;
-            mRefIdleTime = nowIdleTime;
-            
-            const nsecs_t workingTime = nowWorkingTime - mReferenceWorkingTime;
-            const float newCpuUsage = float(workingTime) * reftime;
-            if (mCpuUsage != newCpuUsage) {        
-                mCpuUsage = newCpuUsage;
-                mReferenceWorkingTime = nowWorkingTime;
-                mReferenceTime = now;
-            }
-        }
-        mLock.unlock();
-    }
-}
-
-
-}; // namespace android
diff --git a/libs/surfaceflinger/CPUGauge.h b/libs/surfaceflinger/CPUGauge.h
deleted file mode 100644
index 5bb53c0..0000000
--- a/libs/surfaceflinger/CPUGauge.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_CPUGAUGE_H
-#define ANDROID_CPUGAUGE_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Timers.h>
-
-#include <ui/SurfaceComposerClient.h>
-
-namespace android {
-
-class CPUGauge : public Thread
-{
-public:
-    CPUGauge(   const sp<ISurfaceComposer>& composer,
-                nsecs_t interval=s2ns(1),
-                int clock=SYSTEM_TIME_THREAD,
-                int refclock=SYSTEM_TIME_MONOTONIC);
-                
-    ~CPUGauge();
-
-    const sp<SurfaceComposerClient>& session() const;
-
-    void sample();
- 
-    inline float cpuUsage() const { return mCpuUsage; }
-    inline float idle() const { return mIdleTime; }
-
-private:
-    virtual void        onFirstRef();
-    virtual status_t    readyToRun();
-    virtual bool        threadLoop();
-
-    Mutex mLock;
-
-    sp<SurfaceComposerClient> mSession;
-
-    const nsecs_t mInterval;
-    const int mClock;
-    const int mRefClock;
-
-    nsecs_t mReferenceTime;
-    nsecs_t mReferenceWorkingTime;
-    float mCpuUsage;
-    nsecs_t mRefIdleTime;
-    float mIdleTime;
-    FILE*   mFd;
-};
-
-
-}; // namespace android
-
-#endif // ANDROID_CPUGAUGE_H
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f14d7e9..52b0f68 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -23,18 +21,23 @@
 
 #include <cutils/properties.h>
 
+#include <utils/RefBase.h>
 #include <utils/Log.h>
 
-#include <ui/EGLDisplaySurface.h>
+#include <ui/PixelFormat.h>
+#include <ui/FramebufferNativeWindow.h>
 
 #include <GLES/gl.h>
+#include <EGL/egl.h>
 #include <EGL/eglext.h>
 
+#include <pixelflinger/pixelflinger.h>
 
 #include "DisplayHardware/DisplayHardware.h"
 
 #include <hardware/copybit.h>
 #include <hardware/overlay.h>
+#include <hardware/gralloc.h>
 
 using namespace android;
 
@@ -108,17 +111,28 @@
 
 void DisplayHardware::init(uint32_t dpy)
 {
+    hw_module_t const* module;
+
+    mNativeWindow = new FramebufferNativeWindow();
+
+    mOverlayEngine = NULL;
+    if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
+        overlay_control_open(module, &mOverlayEngine);
+    }
+
+    framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
+
+    PixelFormatInfo fbFormatInfo;
+    getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo);
+
     // initialize EGL
     const EGLint attribs[] = {
-            EGL_RED_SIZE,       5,
-            EGL_GREEN_SIZE,     6,
-            EGL_BLUE_SIZE,      5,
+            EGL_BUFFER_SIZE,    fbFormatInfo.bitsPerPixel,
             EGL_DEPTH_SIZE,     0,
             EGL_NONE
     };
     EGLint w, h, dummy;
-    EGLint numConfigs, n;
-    EGLConfig config;
+    EGLint numConfigs=0, n=0;
     EGLSurface surface;
     EGLContext context;
     mFlags = 0;
@@ -129,7 +143,32 @@
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(display, NULL, NULL);
     eglGetConfigs(display, NULL, 0, &numConfigs);
-    eglChooseConfig(display, attribs, &config, 1, &n);
+
+    // Get all the "potential match" configs...
+    EGLConfig* const configs = new EGLConfig[numConfigs];
+    eglChooseConfig(display, attribs, configs, numConfigs, &n);
+    LOGE_IF(n<=0, "no EGLConfig available!");
+    EGLConfig config = configs[0];
+    if (n > 1) {
+        // if there is more than one candidate, go through the list
+        // and pick one that matches our framebuffer format
+        int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA);
+        int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED);
+        int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN);
+        int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); 
+        for (int i=0 ; i<n ; i++) {
+            EGLint r,g,b,a;
+            eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE,   &r);
+            eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g);
+            eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE,  &b);
+            eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a);
+            if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB  == b) {
+                config = configs[i];
+                break;
+            }
+        }
+    }
+    delete [] configs;
 
     /*
      * Gather EGL extensions
@@ -145,12 +184,11 @@
     LOGI("extensions: %s", egl_extensions);
     LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
 
-    // TODO: get this from the devfb driver (probably should be HAL module)
-    mFlags |= SWAP_RECTANGLE_EXTENSION;
-    
-    // TODO: get the real "update_on_demand" behavior (probably should be HAL module)
-    mFlags |= UPDATE_ON_DEMAND;
 
+    if (mNativeWindow->isUpdateOnDemand()) {
+        mFlags |= UPDATE_ON_DEMAND;
+    }
+    
     if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
         if (dummy == EGL_SLOW_CONFIG)
             mFlags |= SLOW_CONFIG;
@@ -160,33 +198,22 @@
      * Create our main surface
      */
 
-    mDisplaySurface = new EGLDisplaySurface();
-
-    surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
-    //checkEGLErrors("eglCreateDisplaySurfaceANDROID");
+    surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
+    checkEGLErrors("eglCreateDisplaySurfaceANDROID");
 
     if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
         if (dummy == EGL_BUFFER_PRESERVED) {
             mFlags |= BUFFER_PRESERVED;
         }
     }
-    
-    GLint value = EGL_UNKNOWN;
-    eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value);
-    if (value == EGL_UNKNOWN) {
-        mDpiX = 160.0f;
-    } else {
-        mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING;
+
+    if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) {
+        mFlags |= SWAP_RECTANGLE;
     }
-    value = EGL_UNKNOWN;
-    eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value);
-    if (value == EGL_UNKNOWN) {
-        mDpiY = 160.0f;
-    } else {
-        mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
-    }
-    mRefreshRate = 60.f;    // TODO: get the real refresh rate 
-    
+
+    mDpiX = mNativeWindow->xdpi;
+    mDpiX = mNativeWindow->ydpi;
+    mRefreshRate = fbDev->fps; 
     
     char property[PROPERTY_VALUE_MAX];
     if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
@@ -225,7 +252,10 @@
     if (strstr(gl_extensions, "GL_OES_draw_texture")) {
         mFlags |= DRAW_TEXTURE_EXTENSION;
     }
-    if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) {
+    if (strstr( gl_extensions, "GL_OES_EGL_image") &&
+        (strstr(egl_extensions, "EGL_KHR_image_base") || 
+                strstr(egl_extensions, "EGL_KHR_image")) &&
+        strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
         mFlags |= DIRECT_TEXTURE;
     }
 
@@ -236,19 +266,8 @@
     mConfig  = config;
     mSurface = surface;
     mContext = context;
-    mFormat  = GGL_PIXEL_FORMAT_RGB_565;
-    
-    hw_module_t const* module;
-
-    mBlitEngine = NULL;
-    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
-        copybit_open(module, &mBlitEngine);
-    }
-
-    mOverlayEngine = NULL;
-    if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
-        overlay_control_open(module, &mOverlayEngine);
-    }
+    mFormat  = fbDev->format;
+    mPageFlipCount = 0;
 }
 
 /*
@@ -262,7 +281,6 @@
 {
     eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(mDisplay);
-    copybit_close(mBlitEngine);
     overlay_control_close(mOverlayEngine);
 }
 
@@ -276,28 +294,8 @@
     DisplayHardwareBase::acquireScreen();
 }
 
-void DisplayHardware::getDisplaySurface(copybit_image_t* img) const
-{
-    img->w      = mDisplaySurface->stride;
-    img->h      = mDisplaySurface->height;
-    img->format = mDisplaySurface->format;
-    img->offset = mDisplaySurface->offset;
-    img->base   = (void*)mDisplaySurface->base;
-    img->fd     = mDisplaySurface->fd;
-}
-
-void DisplayHardware::getDisplaySurface(GGLSurface* fb) const
-{
-    fb->version= sizeof(GGLSurface);
-    fb->width  = mDisplaySurface->width;
-    fb->height = mDisplaySurface->height;
-    fb->stride = mDisplaySurface->stride;
-    fb->format = mDisplaySurface->format;
-    fb->data   = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset;
-}
-
 uint32_t DisplayHardware::getPageFlipCount() const {
-    return mDisplaySurface->getPageFlipCount();
+    return mPageFlipCount;
 }
 
 /*
@@ -311,21 +309,19 @@
     EGLDisplay dpy = mDisplay;
     EGLSurface surface = mSurface;
 
-    Region newDirty(dirty);
-    newDirty.andSelf(Rect(mWidth, mHeight));
-
-    if (mFlags & BUFFER_PRESERVED) {
-        const Region copyback(mDirty.subtract(newDirty));
-        mDirty = newDirty;
-        mDisplaySurface->copyFrontToBack(copyback);
+    if (mFlags & SWAP_RECTANGLE) {
+        Region newDirty(dirty);
+        newDirty.andSelf(Rect(mWidth, mHeight));
+        const Rect& b(newDirty.bounds());
+        eglSetSwapRectangleANDROID(dpy, surface,
+                b.left, b.top, b.width(), b.height());
     } 
 
-    if (mFlags & SWAP_RECTANGLE_EXTENSION) {
-        const Rect& b(newDirty.bounds());
-        mDisplaySurface->setSwapRectangle(
-                b.left, b.top, b.width(), b.height());
+    if (mFlags & UPDATE_ON_DEMAND) {
+        mNativeWindow->setUpdateRectangle(dirty.bounds());
     }
-
+    
+    mPageFlipCount++;
     eglSwapBuffers(dpy, surface);
     checkEGLErrors("eglSwapBuffers");
 
@@ -345,9 +341,9 @@
 }
 
 void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
-    mDisplaySurface->copyFrontToImage(front);
+    // FIXME: we need to get rid of this
 }
 
 void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
-    mDisplaySurface->copyBackToImage(front);
+    // FIXME: we need to get rid of this
 }
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index 550a4d1..c3dbff1 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -22,31 +22,35 @@
 #include <ui/PixelFormat.h>
 #include <ui/Region.h>
 
+#include <GLES/gl.h>
+#include <GLES/glext.h>
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <pixelflinger/pixelflinger.h>
 
 #include "DisplayHardware/DisplayHardwareBase.h"
 
 struct overlay_control_device_t;
-struct copybit_device_t;
+struct framebuffer_device_t;
 struct copybit_image_t;
-struct copybit_t;
 
 namespace android {
 
-class EGLDisplaySurface;
+class FramebufferNativeWindow;
 
 class DisplayHardware : public DisplayHardwareBase
 {
 public:
     enum {
         DIRECT_TEXTURE          = 0x00000002,
-        SWAP_RECTANGLE_EXTENSION= 0x00000004,
         COPY_BITS_EXTENSION     = 0x00000008,
         NPOT_EXTENSION          = 0x00000100,
         DRAW_TEXTURE_EXTENSION  = 0x00000200,
         BUFFER_PRESERVED        = 0x00010000,
         UPDATE_ON_DEMAND        = 0x00020000,   // video driver feature
         SLOW_CONFIG             = 0x00040000,   // software
+        SWAP_RECTANGLE          = 0x00080000,
     };
 
     DisplayHardware(
@@ -73,10 +77,7 @@
     void        makeCurrent() const;
 
     uint32_t getPageFlipCount() const;
-    void getDisplaySurface(copybit_image_t* img) const;
-    void getDisplaySurface(GGLSurface* fb) const;
     EGLDisplay getEGLDisplay() const { return mDisplay; }
-    copybit_device_t* getBlitEngine() const { return mBlitEngine; }
     overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; }
     
     void copyFrontToImage(const copybit_image_t& front) const;
@@ -102,9 +103,9 @@
     int             mHeight;
     PixelFormat     mFormat;
     uint32_t        mFlags;
-    mutable Region  mDirty;
-    sp<EGLDisplaySurface> mDisplaySurface;
-    copybit_device_t*     mBlitEngine;
+    mutable uint32_t mPageFlipCount;
+    
+    sp<FramebufferNativeWindow> mNativeWindow;
     overlay_control_device_t* mOverlayEngine;
 };
 
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index f75e5c2..1d09f84 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 96395a8..5b260c4 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -14,26 +14,24 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <cutils/properties.h>
+#include <cutils/native_handle.h>
 
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/StopWatch.h>
 
 #include <ui/PixelFormat.h>
-#include <ui/EGLDisplaySurface.h>
+#include <ui/Surface.h>
 
 #include "clz.h"
 #include "Layer.h"
 #include "LayerBitmap.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 #include "DisplayHardware/DisplayHardware.h"
 
 
@@ -54,8 +52,7 @@
         mSecure(false),
         mFrontBufferIndex(1),
         mNeedsBlending(true),
-        mResizeTransactionDone(false),
-        mTextureName(-1U), mTextureWidth(0), mTextureHeight(0)
+        mResizeTransactionDone(false)
 {
     // no OpenGL operation is possible here, since we might not be
     // in the OpenGL thread.
@@ -63,11 +60,22 @@
 
 Layer::~Layer()
 {
-    client->free(clientIndex());
-    // this should always be called from the OpenGL thread
-    if (mTextureName != -1U) {
-        //glDeleteTextures(1, &mTextureName);
-        deletedTextures.add(mTextureName);
+    destroy();
+    // the actual buffers will be destroyed here
+}
+
+void Layer::destroy()
+{
+    for (int i=0 ; i<NUM_BUFFERS ; i++) {
+        if (mTextures[i].name != -1U) {
+            glDeleteTextures(1, &mTextures[i].name);
+            mTextures[i].name = -1U;
+        }
+        if (mTextures[i].image != EGL_NO_IMAGE_KHR) {
+            EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+            eglDestroyImageKHR(dpy, mTextures[i].image);
+            mTextures[i].image = EGL_NO_IMAGE_KHR;
+        }
     }
 }
 
@@ -79,11 +87,19 @@
         lcblk->flags |= eNoCopyBack;
 }
 
-sp<LayerBaseClient::Surface> Layer::getSurface() const
+sp<LayerBaseClient::Surface> Layer::createSurface() const
 {
     return mSurface;
 }
 
+status_t Layer::ditch()
+{
+    // the layer is not on screen anymore. free as much resources as possible
+    mSurface.clear();
+    destroy();
+    return NO_ERROR;
+}
+
 status_t Layer::setBuffers( Client* client,
                             uint32_t w, uint32_t h,
                             PixelFormat format, uint32_t flags)
@@ -92,71 +108,115 @@
     status_t err = getPixelFormatInfo(format, &info);
     if (err) return err;
 
-    // TODO: if eHardware is explicitly requested, we should fail
-    // on systems where we can't allocate memory that can be used with
-    // DMA engines for instance.
-    
-    // FIXME: we always ask for hardware for now (this should come from copybit)
-    flags |= ISurfaceComposer::eHardware;
+    uint32_t bufferFlags = 0;
+    if (flags & ISurfaceComposer::eGPU)
+        bufferFlags |= Buffer::GPU;
 
-    const uint32_t memory_flags = flags & 
-            (ISurfaceComposer::eGPU | 
-             ISurfaceComposer::eHardware | 
-             ISurfaceComposer::eSecure);
-    
-    // pixel-alignment. the final alignment may be bigger because
-    // we always force a 4-byte aligned bpr.
-    uint32_t alignment = 1;
+    if (flags & ISurfaceComposer::eSecure)
+        bufferFlags |= Buffer::SECURE;
 
-    if ((flags & ISurfaceComposer::eGPU) && (mFlinger->getGPU() != 0)) {
-        // FIXME: this value should come from the h/w
-        alignment = 8; 
+    /* FIXME we need this code for msm7201A
+    if (bufferFlags & Buffer::GPU) {
         // FIXME: this is msm7201A specific, as its GPU only supports
         // BGRA_8888.
         if (format == PIXEL_FORMAT_RGBA_8888) {
             format = PIXEL_FORMAT_BGRA_8888;
         }
     }
+    */
 
-    mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
+    mSecure = (bufferFlags & Buffer::SECURE) ? true : false;
     mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
-    sp<MemoryDealer> allocators[2];
     for (int i=0 ; i<2 ; i++) {
-        allocators[i] = client->createAllocator(memory_flags);
-        if (allocators[i] == 0)
-            return NO_MEMORY;
-        mBuffers[i].init(allocators[i]);
-        int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS);
-        if (err != NO_ERROR)
+        err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags);
+        if (err != NO_ERROR) {
             return err;
-        mBuffers[i].clear(); // clear the bits for security
-        mBuffers[i].getInfo(lcblk->surface + i);
+        }
     }
-
-    mSurface = new Surface(clientIndex(),
-            allocators[0]->getMemoryHeap(),
-            allocators[1]->getMemoryHeap(),
-            mIdentity);
-
+    mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
     return NO_ERROR;
 }
 
 void Layer::reloadTexture(const Region& dirty)
 {
-    if (UNLIKELY(mTextureName == -1U)) {
-        // create the texture name the first time
-        // can't do that in the ctor, because it runs in another thread.
-        mTextureName = createTexture();
+    const sp<Buffer>& buffer(frontBuffer().getBuffer());
+    if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) {
+        int index = mFrontBufferIndex;
+        if (LIKELY(!mTextures[index].dirty)) {
+            glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
+        } else {
+            // we need to recreate the texture
+            EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+            
+            // create the new texture name if needed
+            if (UNLIKELY(mTextures[index].name == -1U)) {
+                mTextures[index].name = createTexture();
+            } else {
+                glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
+            }
+
+            // free the previous image
+            if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
+                eglDestroyImageKHR(dpy, mTextures[index].image);
+                mTextures[index].image = EGL_NO_IMAGE_KHR;
+            }
+            
+            // construct an EGL_NATIVE_BUFFER_ANDROID
+            android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+            
+            // create the new EGLImageKHR
+            const EGLint attrs[] = { 
+                    EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE, 
+                    EGL_NONE,                   EGL_NONE 
+            };
+            mTextures[index].image = eglCreateImageKHR(
+                    dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+                    (EGLClientBuffer)clientBuf, attrs);
+
+            LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR,
+                    "eglCreateImageKHR() failed. err=0x%4x",
+                    eglGetError());
+            
+            if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
+                glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, 
+                        (GLeglImageOES)mTextures[index].image);
+                GLint error = glGetError();
+                if (UNLIKELY(error != GL_NO_ERROR)) {
+                    // this failed, for instance, because we don't support
+                    // NPOT.
+                    // FIXME: do something!
+                    mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
+                } else {
+                    // Everything went okay!
+                    mTextures[index].dirty = false;
+                }
+            }                
+        }
+    } else {
+        GGLSurface t;
+        status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY);
+        LOGE_IF(res, "error %d (%s) locking buffer %p",
+                res, strerror(res), buffer.get());
+        if (res == NO_ERROR) {
+            if (UNLIKELY(mTextures[0].name == -1U)) {
+                mTextures[0].name = createTexture();
+            }
+            loadTexture(dirty, mTextures[0].name, t, 
+                    mTextures[0].width, mTextures[0].height);
+            buffer->unlock();
+        }
     }
-    const GGLSurface& t(frontBuffer().surface());
-    loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight);
 }
 
 
 void Layer::onDraw(const Region& clip) const
 {
-    if (UNLIKELY(mTextureName == -1LU)) {
-        //LOGW("Layer %p doesn't have a texture", this);
+    const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ? 
+            mFrontBufferIndex : 0;
+    GLuint textureName = mTextures[index].name;
+
+    if (UNLIKELY(textureName == -1LU)) {
+        LOGW("Layer %p doesn't have a texture", this);
         // the texture has not been created yet, this Layer has
         // in fact never been drawn into. this happens frequently with
         // SurfaceView.
@@ -164,63 +224,65 @@
         return;
     }
 
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    const LayerBitmap& front(frontBuffer());
-    const GGLSurface& t(front.surface());
-
-    status_t err = NO_ERROR;
-    const int can_use_copybit = canUseCopybit();
-    if (can_use_copybit)  {
-        // StopWatch watch("copybit");
-        const State& s(drawingState());
-
-        copybit_image_t dst;
-        hw.getDisplaySurface(&dst);
-        const copybit_rect_t& drect
-            = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
-
-        copybit_image_t src;
-        front.getBitmapSurface(&src);
-        copybit_rect_t srect = { 0, 0, t.width, t.height };
-
-        copybit_device_t* copybit = mFlinger->getBlitEngine();
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation());
-        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
-        copybit->set_parameter(copybit, COPYBIT_DITHER,
-                s.flags & ISurfaceComposer::eLayerDither ?
-                        COPYBIT_ENABLE : COPYBIT_DISABLE);
-
-        region_iterator it(clip);
-        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
-    }
-
-    if (!can_use_copybit || err) {
-        drawWithOpenGL(clip, mTextureName, t);
-    }
+    GGLSurface t;
+    sp<const Buffer> buffer(frontBuffer().getBuffer());
+    drawWithOpenGL(clip, textureName, buffer);
 }
 
-status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
+sp<SurfaceBuffer> Layer::peekBuffer()
 {
-    LOGD_IF(DEBUG_RESIZE,
-                "reallocateBuffer (layer=%p), "
-                "requested (%dx%d), "
-                "index=%d, (%dx%d), (%dx%d)",
-                this,
-                int(w), int(h),
-                int(index),
-                int(mBuffers[0].width()), int(mBuffers[0].height()),
-                int(mBuffers[1].width()), int(mBuffers[1].height()));
+    /*
+     * This is called from the client's Surface::lock(), after it locked
+     * the surface successfully. We're therefore guaranteed that the
+     * back-buffer is not in use by ourselves.
+     * Of course, we need to validate all this, which is not trivial.
+     *
+     * FIXME: A resize could happen at any time here. What to do about this?
+     *  - resize() form post()
+     *  - resize() from doTransaction()
+     *  
+     *  We'll probably need an internal lock for this.
+     *     
+     * 
+     * TODO: We need to make sure that post() doesn't swap
+     *       the buffers under us.
+     */
 
-    status_t err = mBuffers[index].resize(w, h);
-    if (err == NO_ERROR) {
-        mBuffers[index].getInfo(lcblk->surface + index);
-    } else {
-        LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
-            index, w, h, err, strerror(err));
-        // XXX: what to do, what to do? We could try to free some
-        // hidden surfaces, instead of killing this one?
+    // it's okay to read swapState for the purpose of figuring out the 
+    // backbuffer index, which cannot change (since the app has locked it).
+    const uint32_t state = lcblk->swapState;
+    const int32_t backBufferIndex = layer_cblk_t::backBuffer(state);
+    
+    // get rid of the EGL image, since we shouldn't need it anymore
+    // (note that we're in a different thread than where it is being used)
+    if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) {
+        EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+        eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image);
+        mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR;
     }
-    return err;
+    
+    LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
+    sp<SurfaceBuffer> buffer = layerBitmap.allocate();
+    
+    LOGD_IF(DEBUG_RESIZE,
+            "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
+            this, backBufferIndex,
+            layerBitmap.getWidth(),
+            layerBitmap.getHeight(),
+            layerBitmap.getBuffer()->getWidth(),
+            layerBitmap.getBuffer()->getHeight());
+
+    if (UNLIKELY(buffer == 0)) {
+        // XXX: what to do, what to do?
+    } else {
+        // texture is now dirty...
+        mTextures[backBufferIndex].dirty = true;
+        // ... so it the visible region (because we consider the surface's
+        // buffer size for visibility calculations)
+        forceVisibilityTransaction();
+        mFlinger->setTransactionFlags(eTraversalNeeded);
+    }
+    return buffer;
 }
 
 uint32_t Layer::doTransaction(uint32_t flags)
@@ -232,7 +294,7 @@
     // that the size changed back to its previous value before the buffer
     // was resized (in the eLocked case below), in which case, we still
     // need to execute the code below so the clients have a chance to be
-    // release. resze() deals with the fact that the size can be the same.
+    // release. resize() deals with the fact that the size can be the same.
 
     /*
      *  Various states we could be in...
@@ -276,8 +338,8 @@
                 int(temp.w), int(temp.h),
                 int(drawingState().w), int(drawingState().h),
                 int(clientBackBufferIndex),
-                int(mBuffers[0].width()), int(mBuffers[0].height()),
-                int(mBuffers[1].width()), int(mBuffers[1].height()));
+                int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
+                int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
         // if we get there we're pretty screwed. the only reasonable
         // thing to do is to pretend we should do the resize since
         // backbufferChanged is set (this also will give a chance to
@@ -299,8 +361,8 @@
                     int(temp.w), int(temp.h),
                     int(drawingState().w), int(drawingState().h),
                     int(clientBackBufferIndex),
-                    int(mBuffers[0].width()), int(mBuffers[0].height()),
-                    int(mBuffers[1].width()), int(mBuffers[1].height()));
+                    int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
+                    int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
 
         if (state & eLocked) {
             // if the buffer is locked, we can't resize anything because
@@ -314,7 +376,8 @@
             status_t err =
                 resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
             if (err == NO_ERROR) {
-                const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
+                const uint32_t mask = clientBackBufferIndex ?
+                        eResizeBuffer1 : eResizeBuffer0;
                 android_atomic_and(~mask, &(lcblk->swapState));
                 // since a buffer became available, we can let the client go...
                 mFlinger->scheduleBroadcast(client);
@@ -353,14 +416,15 @@
 {
     /*
      * handle resize (backbuffer and frontbuffer reallocation)
+     * this is called from post() or from doTransaction()
      */
 
     const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);
 
     // if the new (transaction) size is != from the the backbuffer
     // then we need to reallocate the backbuffer
-    bool backbufferChanged = (clientBackBuffer.width()  != width) ||
-                             (clientBackBuffer.height() != height);
+    bool backbufferChanged = (clientBackBuffer.getWidth()  != width) ||
+                             (clientBackBuffer.getHeight() != height);
 
     LOGD_IF(!backbufferChanged,
             "(%s) eResizeRequested (layer=%p), but size not changed: "
@@ -372,18 +436,28 @@
             int(currentState().w), int(currentState().h),
             long(lcblk->swapState),
             int(clientBackBufferIndex),
-            int(mBuffers[0].width()), int(mBuffers[0].height()),
-            int(mBuffers[1].width()), int(mBuffers[1].height()));
+            int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
+            int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
 
     // this can happen when changing the size back and forth quickly
     status_t err = NO_ERROR;
     if (backbufferChanged) {
-        err = reallocateBuffer(clientBackBufferIndex, width, height);
-    }
-    if (UNLIKELY(err != NO_ERROR)) {
-        // couldn't reallocate the surface
-        android_atomic_write(eInvalidSurface, &lcblk->swapState);
-        memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t));
+
+        LOGD_IF(DEBUG_RESIZE,
+                "resize (layer=%p), requested (%dx%d), "
+                "index=%d, (%dx%d), (%dx%d)",
+                this, int(width), int(height), int(clientBackBufferIndex),
+                int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
+                int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
+
+        err = mBuffers[clientBackBufferIndex].setSize(width, height);
+        if (UNLIKELY(err != NO_ERROR)) {
+            // This really should never happen
+            LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
+                    clientBackBufferIndex, width, height, err, strerror(err));
+            // couldn't reallocate the surface
+            android_atomic_write(eInvalidSurface, &lcblk->swapState);
+        }
     }
     return err;
 }
@@ -457,15 +531,21 @@
 
     } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
     *previousSate = oldValue;
-
+    
     const int32_t index = (newValue & eIndex) ^ 1;
     mFrontBufferIndex = index;
 
+    /* NOTE: it's safe to set this flag here because this is only touched
+     * from LayerBitmap::allocate(), which by construction cannot happen
+     * while we're in post().
+     */
+    lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty;
+
     // ... post the new front-buffer
     Region dirty(lcblk->region + index);
-    dirty.andSelf(frontBuffer().bounds());
+    dirty.andSelf(frontBuffer().getBounds());
 
-    //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
+    //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
     //    oldValue, newValue, mFrontBufferIndex);
     //dirty.dump("dirty");
 
@@ -476,8 +556,8 @@
                      "index=%d, (%dx%d), (%dx%d)",
                      this,  newValue,
                      int(1-index),
-                     int(mBuffers[0].width()), int(mBuffers[0].height()),
-                     int(mBuffers[1].width()), int(mBuffers[1].height()));
+                     int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
+                     int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
 
         // here, we just posted the surface and we have resolved
         // the front/back buffer indices. The client is blocked, so
@@ -522,8 +602,8 @@
 
 Point Layer::getPhysicalSize() const
 {
-    const LayerBitmap& front(frontBuffer());
-    return Point(front.width(), front.height());
+    sp<const Buffer> front(frontBuffer().getBuffer());
+    return Point(front->getWidth(), front->getHeight());
 }
 
 void Layer::unlockPageFlip(
@@ -561,6 +641,27 @@
     mFlinger->scheduleBroadcast(client);
 }
 
+// ---------------------------------------------------------------------------
+
+Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
+        SurfaceID id, const sp<Layer>& owner)
+    : Surface(flinger, id, owner->getIdentity(), owner)
+{
+}
+
+Layer::SurfaceLayer::~SurfaceLayer()
+{
+}
+
+sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer()
+{
+    sp<SurfaceBuffer> buffer = 0;
+    sp<Layer> owner(getOwner());
+    if (owner != 0) {
+        buffer = owner->peekBuffer();
+    }
+    return buffer;
+}
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 2867f2b..e16d9f4 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -27,6 +27,11 @@
 
 #include <pixelflinger/pixelflinger.h>
 
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
 #include "LayerBitmap.h"
 #include "LayerBase.h"
 #include "Transform.h"
@@ -42,6 +47,8 @@
 
 // ---------------------------------------------------------------------------
 
+const int NUM_BUFFERS = 2;
+
 class Layer : public LayerBaseClient
 {
 public:    
@@ -56,7 +63,7 @@
         virtual ~Layer();
 
     inline PixelFormat pixelFormat() const {
-        return frontBuffer().pixelFormat();
+        return frontBuffer().getPixelFormat();
     }
 
     status_t setBuffers(    Client* client,
@@ -73,8 +80,8 @@
     virtual void finishPageFlip();
     virtual bool needsBlending() const      { return mNeedsBlending; }
     virtual bool isSecure() const           { return mSecure; }
-    virtual GLuint getTextureName() const   { return mTextureName; }
-    virtual sp<Surface> getSurface() const;
+    virtual sp<Surface> createSurface() const;
+    virtual status_t ditch();
 
     const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; }
           LayerBitmap& getBuffer(int i)       { return mBuffers[i]; }
@@ -96,21 +103,46 @@
 
     status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what);
     Region post(uint32_t* oldState, bool& recomputeVisibleRegions);
-    status_t reallocateBuffer(int32_t index, uint32_t w, uint32_t h);
+    sp<SurfaceBuffer> peekBuffer();
+    void destroy();
 
+    
+    class SurfaceLayer : public LayerBaseClient::Surface
+    {
+    public:
+                SurfaceLayer(const sp<SurfaceFlinger>& flinger,
+                        SurfaceID id, const sp<Layer>& owner);
+                ~SurfaceLayer();
+
+    private:
+        virtual sp<SurfaceBuffer> getBuffer();
+
+        sp<Layer> getOwner() const {
+            return static_cast<Layer*>(Surface::getOwner().get());
+        }
+    };
+    friend class SurfaceLayer;
+    
+    struct Texture {
+        Texture() : name(-1U), width(0), height(0), image(EGL_NO_IMAGE_KHR),
+            dirty(true) { }
+        GLuint      name;
+        GLuint      width;
+        GLuint      height;
+        EGLImageKHR image;
+        bool        dirty;
+    };
+    
     sp<Surface>             mSurface;
 
             bool            mSecure;
-            LayerBitmap     mBuffers[2];
+            LayerBitmap     mBuffers[NUM_BUFFERS];
+            Texture         mTextures[NUM_BUFFERS];
             int32_t         mFrontBufferIndex;
             bool            mNeedsBlending;
             bool            mResizeTransactionDone;
             Region          mPostedDirtyRegion;
             sp<FreezeLock>  mFreezeLock;
-            
-            GLuint          mTextureName;
-            GLuint          mTextureWidth;
-            GLuint          mTextureHeight;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 0cf53f7..c678711 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <utils/Errors.h>
 #include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
@@ -53,8 +53,6 @@
 
 // ---------------------------------------------------------------------------
 
-Vector<GLuint> LayerBase::deletedTextures; 
-
 int32_t LayerBase::sIdentity = 0;
 
 LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
@@ -62,7 +60,6 @@
       mFlinger(flinger),
       mTransformed(false),
       mOrientation(0),
-      mCanUseCopyBit(false),
       mTransactionFlags(0),
       mPremultipliedAlpha(true),
       mIdentity(uint32_t(android_atomic_inc(&sIdentity))),
@@ -265,43 +262,6 @@
     mTransformed = transformed;
     mLeft = tr.tx();
     mTop  = tr.ty();
-
-    // see if we can/should use 2D h/w with the new configuration
-    mCanUseCopyBit = false;
-    copybit_device_t* copybit = mFlinger->getBlitEngine();
-    if (copybit) { 
-        const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG);
-        const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS);
-        mCanUseCopyBit = true;
-        if ((mOrientation < 0) && (step > 1)) {
-            // arbitrary orientations not supported
-            mCanUseCopyBit = false;
-        } else if ((mOrientation > 0) && (step > 90)) {
-            // 90 deg rotations not supported
-            mCanUseCopyBit = false;
-        } else if ((tr.getType() & SkMatrix::kScale_Mask) && (scaleBits < 12)) { 
-            // arbitrary scaling not supported
-            mCanUseCopyBit = false;
-        }
-#if HONOR_PREMULTIPLIED_ALPHA 
-        else if (needsBlending() && mPremultipliedAlpha) {
-            // pre-multiplied alpha not supported
-            mCanUseCopyBit = false;
-        }
-#endif
-        else {
-            // here, we determined we can use copybit
-            if (tr.getType() & SkMatrix::kScale_Mask) {
-                // and we have scaling
-                if (!transparentRegionScreen.isRect()) {
-                    // we punt because blending is cheap (h/w) and the region is
-                    // complex, which may causes artifacts when copying
-                    // scaled content
-                    transparentRegionScreen.clear();
-                }
-            }
-        }
-    }
 }
 
 void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
@@ -329,8 +289,9 @@
 
 void LayerBase::drawRegion(const Region& reg) const
 {
-    Region::iterator iterator(reg);
-    if (iterator) {
+    Region::const_iterator it = reg.begin();
+    Region::const_iterator const end = reg.end();
+    if (it != end) {
         Rect r;
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
         const int32_t fbWidth  = hw.getWidth();
@@ -338,7 +299,8 @@
         const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, 
                 { fbWidth, fbHeight }, { 0, fbHeight }  };
         glVertexPointer(2, GL_SHORT, 0, vertices);
-        while (iterator.iterate(&r)) {
+        while (it != end) {
+            const Rect& r = *it++;
             const GLint sy = fbHeight - (r.top + r.height());
             glScissor(r.left, sy, r.width(), r.height());
             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
@@ -403,12 +365,14 @@
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_BLEND);
     glDisable(GL_DITHER);
-    Rect r;
-    Region::iterator iterator(clip);
-    if (iterator) {
+
+    Region::const_iterator it = clip.begin();
+    Region::const_iterator const end = clip.end();
+    if (it != end) {
         glEnable(GL_SCISSOR_TEST);
         glVertexPointer(2, GL_FIXED, 0, mVertices);
-        while (iterator.iterate(&r)) {
+        while (it != end) {
+            const Rect& r = *it++;
             const GLint sy = fbHeight - (r.top + r.height());
             glScissor(r.left, sy, r.width(), r.height());
             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
@@ -417,12 +381,14 @@
 }
 
 void LayerBase::drawWithOpenGL(const Region& clip,
-        GLint textureName, const GGLSurface& t, int transform) const
+        GLint textureName, const sp<const Buffer>& buffer, int transform) const
 {
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     const uint32_t fbHeight = hw.getHeight();
     const State& s(drawingState());
-
+    const uint32_t width = buffer->width;
+    const uint32_t height = buffer->height;
+    
     // bind our texture
     validateTexture(textureName);
     glEnable(GL_TEXTURE_2D);
@@ -472,8 +438,9 @@
             || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) 
     {
         //StopWatch watch("GL transformed");
-        Region::iterator iterator(clip);
-        if (iterator) {
+        Region::const_iterator it = clip.begin();
+        Region::const_iterator const end = clip.end();
+        if (it != end) {
             // always use high-quality filtering with fast configurations
             bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG);
             if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
@@ -497,14 +464,14 @@
 
             if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
                 // find the smallest power-of-two that will accommodate our surface
-                GLuint tw = 1 << (31 - clz(t.width));
-                GLuint th = 1 << (31 - clz(t.height));
-                if (tw < t.width)  tw <<= 1;
-                if (th < t.height) th <<= 1;
+                GLuint tw = 1 << (31 - clz(width));
+                GLuint th = 1 << (31 - clz(height));
+                if (tw < width)  tw <<= 1;
+                if (th < height) th <<= 1;
                 // this divide should be relatively fast because it's
                 // a power-of-two (optimized path in libgcc)
-                GLfloat ws = GLfloat(t.width) /tw;
-                GLfloat hs = GLfloat(t.height)/th;
+                GLfloat ws = GLfloat(width) /tw;
+                GLfloat hs = GLfloat(height)/th;
                 glScalef(ws, hs, 1.0f);
             }
 
@@ -512,8 +479,8 @@
             glVertexPointer(2, GL_FIXED, 0, mVertices);
             glTexCoordPointer(2, GL_FIXED, 0, texCoords);
 
-            Rect r;
-            while (iterator.iterate(&r)) {
+            while (it != end) {
+                const Rect& r = *it++;
                 const GLint sy = fbHeight - (r.top + r.height());
                 glScissor(r.left, sy, r.width(), r.height());
                 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
@@ -526,18 +493,19 @@
             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
         }
     } else {
-        Region::iterator iterator(clip);
-        if (iterator) {
-            Rect r;
-            GLint crop[4] = { 0, t.height, t.width, -t.height };
+        Region::const_iterator it = clip.begin();
+        Region::const_iterator const end = clip.end();
+        if (it != end) {
+            GLint crop[4] = { 0, height, width, -height };
             glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
             int x = tx();
             int y = ty();
-            y = fbHeight - (y + t.height);
-            while (iterator.iterate(&r)) {
+            y = fbHeight - (y + height);
+            while (it != end) {
+                const Rect& r = *it++;
                 const GLint sy = fbHeight - (r.top + r.height());
                 glScissor(r.left, sy, r.width(), r.height());
-                glDrawTexiOES(x, y, 0, t.width, t.height);
+                glDrawTexiOES(x, y, 0, width, height);
             }
         }
     }
@@ -565,8 +533,7 @@
 
     /*
      * In OpenGL ES we can't specify a stride with glTexImage2D (however,
-     * GL_UNPACK_ALIGNMENT is 4, which in essence allows a limited form of
-     * stride).
+     * GL_UNPACK_ALIGNMENT is a limited form of stride).
      * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
      * need to do something reasonable (here creating a bigger texture).
      * 
@@ -579,9 +546,11 @@
      *
      * This should never be a problem with POT textures
      */
-
-    tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4);
-
+    
+    int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format));
+    unpack = 1 << ((unpack > 3) ? 3 : unpack);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
+    
     /*
      * round to POT if needed 
      */
@@ -594,108 +563,80 @@
         texture_h = 1 << (31 - clz(t.height));
         if (texture_w < t.width)  texture_w <<= 1;
         if (texture_h < t.height) texture_h <<= 1;
-        if (texture_w != tw || texture_h != th) {
-            // we can't use DIRECT_TEXTURE since we changed the size
-            // of the texture
-            flags &= ~DisplayHardware::DIRECT_TEXTURE;
-        }
     }
-
-    if (flags & DisplayHardware::DIRECT_TEXTURE) {
-        // here we're guaranteed that texture_{w|h} == t{w|h}
-        if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
-            glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
-                    GL_RGB, tw, th, 0,
-                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data);
-        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
-            glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
-                    GL_RGBA, tw, th, 0,
-                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data);
-        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
-            glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
-                    GL_RGBA, tw, th, 0,
-                    GL_RGBA, GL_UNSIGNED_BYTE, t.data);
-        } else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) {
-            // TODO: add GL_BGRA extension
-        } else {
-            // oops, we don't handle this format, try the regular path
-            goto regular;
-        }
-        textureWidth = tw;
-        textureHeight = th;
-    } else {
+    
 regular:
-        Rect bounds(dirty.bounds());
-        GLvoid* data = 0;
-        if (texture_w!=textureWidth || texture_h!=textureHeight) {
-            // texture size changed, we need to create a new one
+    Rect bounds(dirty.bounds());
+    GLvoid* data = 0;
+    if (texture_w!=textureWidth || texture_h!=textureHeight) {
+        // texture size changed, we need to create a new one
 
-            if (!textureWidth || !textureHeight) {
-                // this is the first time, load the whole texture
-                if (texture_w==tw && texture_h==th) {
-                    // we can do it one pass
-                    data = t.data;
-                } else {
-                    // we have to create the texture first because it
-                    // doesn't match the size of the buffer
-                    bounds.set(Rect(tw, th));
-                }
-            }
-            
-            if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
-                glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_RGB, texture_w, texture_h, 0,
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
-            } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
-                glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_RGBA, texture_w, texture_h, 0,
-                        GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
-            } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
-                glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_RGBA, texture_w, texture_h, 0,
-                        GL_RGBA, GL_UNSIGNED_BYTE, data);
-            } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
-                        t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
-                // just show the Y plane of YUV buffers
+        if (!textureWidth || !textureHeight) {
+            // this is the first time, load the whole texture
+            if (texture_w==tw && texture_h==th) {
+                // we can do it one pass
                 data = t.data;
-                glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_LUMINANCE, texture_w, texture_h, 0,
-                        GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
             } else {
-                // oops, we don't handle this format!
-                LOGE("layer %p, texture=%d, using format %d, which is not "
-                     "supported by the GL", this, textureName, t.format);
-                textureName = -1;
+                // we have to create the texture first because it
+                // doesn't match the size of the buffer
+                bounds.set(Rect(tw, th));
             }
-            textureWidth = texture_w;
-            textureHeight = texture_h;
         }
-        if (!data && textureName>=0) {
-            if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
-                glTexSubImage2D(GL_TEXTURE_2D, 0,
-                        0, bounds.top, t.width, bounds.height(),
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
-                        t.data + bounds.top*t.width*2);
-            } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
-                glTexSubImage2D(GL_TEXTURE_2D, 0,
-                        0, bounds.top, t.width, bounds.height(),
-                        GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
-                        t.data + bounds.top*t.width*2);
-            } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
-                glTexSubImage2D(GL_TEXTURE_2D, 0,
-                        0, bounds.top, t.width, bounds.height(),
-                        GL_RGBA, GL_UNSIGNED_BYTE,
-                        t.data + bounds.top*t.width*4);
-            }
+        
+        if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
+            glTexImage2D(GL_TEXTURE_2D, 0,
+                    GL_RGB, texture_w, texture_h, 0,
+                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
+        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
+            glTexImage2D(GL_TEXTURE_2D, 0,
+                    GL_RGBA, texture_w, texture_h, 0,
+                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
+        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
+            glTexImage2D(GL_TEXTURE_2D, 0,
+                    GL_RGBA, texture_w, texture_h, 0,
+                    GL_RGBA, GL_UNSIGNED_BYTE, data);
+        } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
+                    t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
+            // just show the Y plane of YUV buffers
+            glTexImage2D(GL_TEXTURE_2D, 0,
+                    GL_LUMINANCE, texture_w, texture_h, 0,
+                    GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
+        } else {
+            // oops, we don't handle this format!
+            LOGE("layer %p, texture=%d, using format %d, which is not "
+                 "supported by the GL", this, textureName, t.format);
+            textureName = -1;
+        }
+        textureWidth = texture_w;
+        textureHeight = texture_h;
+    }
+    if (!data && textureName>=0) {
+        if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                    0, bounds.top, t.width, bounds.height(),
+                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+                    t.data + bounds.top*t.stride*2);
+        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                    0, bounds.top, t.width, bounds.height(),
+                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
+                    t.data + bounds.top*t.stride*2);
+        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                    0, bounds.top, t.width, bounds.height(),
+                    GL_RGBA, GL_UNSIGNED_BYTE,
+                    t.data + bounds.top*t.stride*4);
+        } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
+                    t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
+            // just show the Y plane of YUV buffers
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                    0, bounds.top, t.width, bounds.height(),
+                    GL_LUMINANCE, GL_UNSIGNED_BYTE,
+                    t.data + bounds.top*t.stride);
         }
     }
 }
 
-bool LayerBase::canUseCopybit() const
-{
-    return mCanUseCopyBit;
-}
-
 // ---------------------------------------------------------------------------
 
 LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
@@ -704,9 +645,12 @@
       lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ),
       mIndex(i)
 {
-    if (client) {
-        client->bindLayer(this, i);
+}
 
+void LayerBaseClient::onFirstRef()
+{    
+    if (client) {
+        client->bindLayer(this, mIndex);
         // Initialize this layer's control block
         memset(this->lcblk, 0, sizeof(layer_cblk_t));
         this->lcblk->identity = mIdentity;
@@ -729,11 +673,113 @@
     return 0xFFFF0000 | mIndex;
 }
 
-sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const
+sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
 {
-    return new Surface(clientIndex(), mIdentity);
+    sp<Surface> s;
+    Mutex::Autolock _l(mLock);
+    s = mClientSurface.promote();
+    if (s == 0) {
+        s = createSurface();
+        mClientSurface = s;
+    }
+    return s;
 }
 
+sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
+{
+    return new Surface(mFlinger, clientIndex(), mIdentity,
+            const_cast<LayerBaseClient *>(this));
+}
+
+// ---------------------------------------------------------------------------
+
+LayerBaseClient::Surface::Surface(
+        const sp<SurfaceFlinger>& flinger,
+        SurfaceID id, int identity, 
+        const sp<LayerBaseClient>& owner) 
+    : mFlinger(flinger), mToken(id), mIdentity(identity), mOwner(owner)
+{
+}
+
+
+LayerBaseClient::Surface::~Surface() 
+{
+    /*
+     * This is a good place to clean-up all client resources 
+     */
+
+    // destroy client resources
+    sp<LayerBaseClient> layer = getOwner();
+    if (layer != 0) {
+        mFlinger->destroySurface(layer);
+    }
+}
+
+sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
+    sp<LayerBaseClient> owner(mOwner.promote());
+    return owner;
+}
+
+
+void LayerBaseClient::Surface::getSurfaceData(
+        ISurfaceFlingerClient::surface_data_t* params) const 
+{
+    params->token = mToken;
+    params->identity = mIdentity;
+}
+
+status_t LayerBaseClient::Surface::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case REGISTER_BUFFERS:
+        case UNREGISTER_BUFFERS:
+        case CREATE_OVERLAY:
+        {
+            // codes that require permission check
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int self_pid = getpid();
+            if (LIKELY(pid != self_pid)) {
+                // we're called from a different process, do the real check
+                if (!checkCallingPermission(
+                        String16("android.permission.ACCESS_SURFACE_FLINGER")))
+                {
+                    const int uid = ipc->getCallingUid();
+                    LOGE("Permission Denial: "
+                            "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
+                    return PERMISSION_DENIED;
+                }
+            }
+        }
+    }
+    return BnSurface::onTransact(code, data, reply, flags);
+}
+
+sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer() 
+{
+    return NULL; 
+}
+
+status_t LayerBaseClient::Surface::registerBuffers(
+        const ISurface::BufferHeap& buffers) 
+{ 
+    return INVALID_OPERATION; 
+}
+
+void LayerBaseClient::Surface::postBuffer(ssize_t offset) 
+{
+}
+
+void LayerBaseClient::Surface::unregisterBuffers() 
+{
+}
+
+sp<OverlayRef> LayerBaseClient::Surface::createOverlay(
+        uint32_t w, uint32_t h, int32_t format) 
+{
+    return NULL;
+};
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index a020f44..509dedd 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -22,6 +22,8 @@
 
 #include <private/ui/LayerState.h>
 
+#include <utils/RefBase.h>
+
 #include <ui/Region.h>
 #include <ui/Overlay.h>
 
@@ -37,10 +39,12 @@
 class DisplayHardware;
 class GraphicPlane;
 class Client;
+class SurfaceBuffer;
+class Buffer;
 
 // ---------------------------------------------------------------------------
 
-class LayerBase
+class LayerBase : public RefBase
 {
     // poor man's dynamic_cast below
     template<typename T>
@@ -69,10 +73,7 @@
     }
 
     
-    static Vector<GLuint> deletedTextures; 
-
     LayerBase(SurfaceFlinger* flinger, DisplayID display);
-    virtual ~LayerBase();
     
     DisplayID           dpy;
     mutable bool        contentDirty;
@@ -201,21 +202,29 @@
 
     /**
      * isSecure - true if this surface is secure, that is if it prevents
-     * screenshots or vns servers.
+     * screenshots or VNC servers.
      */
     virtual bool isSecure() const       { return false; }
 
-            enum { // flags for doTransaction()
-                eVisibleRegion      = 0x00000002,
-                eRestartTransaction = 0x00000008
-            };
+    /** signal this layer that it's not needed any longer. called from the 
+     * main thread */
+    virtual status_t ditch() { return NO_ERROR; }
+
+    
+    
+    enum { // flags for doTransaction()
+        eVisibleRegion      = 0x00000002,
+        eRestartTransaction = 0x00000008
+    };
 
 
     inline  const State&    drawingState() const    { return mDrawingState; }
     inline  const State&    currentState() const    { return mCurrentState; }
     inline  State&          currentState()          { return mCurrentState; }
 
-    static int compareCurrentStateZ(LayerBase*const* layerA, LayerBase*const* layerB) {
+    static int compareCurrentStateZ(
+            sp<LayerBase> const * layerA,
+            sp<LayerBase> const * layerB) {
         return layerA[0]->currentState().z - layerB[0]->currentState().z;
     }
 
@@ -231,7 +240,7 @@
     
           void drawWithOpenGL(const Region& clip,
                   GLint textureName,
-                  const GGLSurface& surface,
+                  const sp<const Buffer>& buffer,
                   int transform = 0) const;
 
           void clearWithOpenGL(const Region& clip) const;
@@ -240,9 +249,7 @@
                   GLint textureName, const GGLSurface& t,
                   GLuint& textureWidth, GLuint& textureHeight) const;
 
-          bool canUseCopybit() const;
-          
-                SurfaceFlinger* mFlinger;
+                sp<SurfaceFlinger> mFlinger;
                 uint32_t        mFlags;
 
                 // cached during validateVisibility()
@@ -250,7 +257,6 @@
                 int32_t         mOrientation;
                 GLfixed         mVertices[4][2];
                 Rect            mTransformedBounds;
-                bool            mCanUseCopyBit;
                 int             mLeft;
                 int             mTop;
             
@@ -269,9 +275,13 @@
     volatile    int32_t         mInvalidate;
                 
 
+protected:
+    virtual ~LayerBase();
+
 private:
-                void validateTexture(GLint textureName) const;
-    static      int32_t         sIdentity;
+    LayerBase(const LayerBase& rhs);
+    void validateTexture(GLint textureName) const;
+    static int32_t sIdentity;
 };
 
 
@@ -289,64 +299,58 @@
     LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, 
             Client* client, int32_t i);
     virtual ~LayerBaseClient();
-
+    virtual void onFirstRef();
 
     Client*             const client;
     layer_cblk_t*       const lcblk;
 
+    inline  uint32_t    getIdentity() const { return mIdentity; }
     inline  int32_t     clientIndex() const { return mIndex; }
             int32_t     serverIndex() const;
 
-    virtual sp<Surface> getSurface() const;
    
-            uint32_t    getIdentity() const { return mIdentity; }
+            sp<Surface> getSurface();
+    virtual sp<Surface> createSurface() const;
+    
 
     class Surface : public BnSurface 
     {
     public:
-        Surface(SurfaceID id, int identity) { 
-            mParams.token = id;
-            mParams.identity = identity;
-        }
-        Surface(SurfaceID id, 
-                const sp<IMemoryHeap>& heap0,
-                const sp<IMemoryHeap>& heap1,
-                int identity)
-        {
-            mParams.token = id;
-            mParams.identity = identity;
-            mParams.heap[0] = heap0;
-            mParams.heap[1] = heap1;
-        }
-        virtual ~Surface() {
-            // TODO: We now have a point here were we can clean-up the
-            // client's mess.
-            // This is also where surface id should be recycled.
-            //LOGD("Surface %d, heaps={%p, %p} destroyed",
-            //        mId, mHeap[0].get(), mHeap[1].get());
-        }
-
+        
         virtual void getSurfaceData(
-                ISurfaceFlingerClient::surface_data_t* params) const {
-            *params = mParams;
-        }
+                ISurfaceFlingerClient::surface_data_t* params) const;
 
-        virtual status_t registerBuffers(const ISurface::BufferHeap& buffers) 
-                { return INVALID_OPERATION; }
-        virtual void postBuffer(ssize_t offset) { }
-        virtual void unregisterBuffers() { };
-        virtual sp<OverlayRef> createOverlay(
-                uint32_t w, uint32_t h, int32_t format) {
-            return NULL;
-        };
+    protected:
+        Surface(const sp<SurfaceFlinger>& flinger, 
+                SurfaceID id, int identity, 
+                const sp<LayerBaseClient>& owner);
+        virtual ~Surface();
+        virtual status_t onTransact(uint32_t code, const Parcel& data,
+                Parcel* reply, uint32_t flags);
+        sp<LayerBaseClient> getOwner() const;
 
     private:
-        ISurfaceFlingerClient::surface_data_t mParams;
+        virtual sp<SurfaceBuffer> getBuffer();
+        virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); 
+        virtual void postBuffer(ssize_t offset);
+        virtual void unregisterBuffers();
+        virtual sp<OverlayRef> createOverlay(uint32_t w, uint32_t h,
+                int32_t format);
+
+    protected:
+        friend class LayerBaseClient;
+        sp<SurfaceFlinger>  mFlinger;
+        int32_t             mToken;
+        int32_t             mIdentity;
+        wp<LayerBaseClient> mOwner;
     };
 
-private:
-    int32_t mIndex;
+    friend class Surface;
 
+private:
+                int32_t         mIndex;
+    mutable     Mutex           mLock;
+    mutable     wp<Surface>     mClientSurface;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index eb3c3e5..a368ca9 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -14,172 +14,190 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <cutils/memory.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <binder/MemoryDealer.h>
+#include <binder/MemoryBase.h>
 #include <binder/IMemory.h>
+
 #include <ui/PixelFormat.h>
+#include <ui/Surface.h>
 #include <pixelflinger/pixelflinger.h>
 
+#include "BufferAllocator.h"
 #include "LayerBitmap.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 
 
 namespace android {
 
-// ---------------------------------------------------------------------------
+// ===========================================================================
+// Buffer and implementation of android_native_buffer_t
+// ===========================================================================
+
+Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+    : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags), 
+    mVStride(0)
+{
+    this->format = format;
+    if (w>0 && h>0) {
+        mInitCheck = initSize(w, h);
+    }
+}
+
+Buffer::~Buffer()
+{
+    if (handle) {
+        BufferAllocator& allocator(BufferAllocator::get());
+        allocator.free(handle);
+    }
+}
+
+status_t Buffer::initCheck() const {
+    return mInitCheck;
+}
+
+android_native_buffer_t* Buffer::getNativeBuffer() const
+{
+    return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this));
+}
+
+status_t Buffer::initSize(uint32_t w, uint32_t h)
+{
+    status_t err = NO_ERROR;
+
+    BufferAllocator& allocator = BufferAllocator::get();
+        
+    /*
+     *  buffers used for software rendering, but h/w composition
+     *  are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
+     *  
+     *  buffers used for h/w rendering and h/w composition
+     *  are allocated with  HW_RENDER | HW_TEXTURE
+     *  
+     *  buffers used with h/w rendering and either NPOT or no egl_image_ext
+     *  are allocated with SW_READ_RARELY | HW_RENDER 
+     *  
+     */
+    
+    if (mFlags & Buffer::SECURE) {
+        // secure buffer, don't store it into the GPU
+        usage = BufferAllocator::USAGE_SW_READ_OFTEN | 
+                BufferAllocator::USAGE_SW_WRITE_OFTEN;
+    } else {
+        if (mFlags & Buffer::GPU) {
+            // the client wants to do GL rendering
+            usage = BufferAllocator::USAGE_HW_RENDER |
+                    BufferAllocator::USAGE_HW_TEXTURE;
+        } else {
+            // software rendering-client, h/w composition
+            usage = BufferAllocator::USAGE_SW_READ_OFTEN | 
+                    BufferAllocator::USAGE_SW_WRITE_OFTEN |
+                    BufferAllocator::USAGE_HW_TEXTURE;
+        }
+    }
+
+    err = allocator.alloc(w, h, format, usage, &handle, &stride);
+    
+    if (err == NO_ERROR) {
+        if (err == NO_ERROR) {
+            width  = w;
+            height = h;
+            mVStride = 0;
+        }
+    }
+
+    return err;
+}
+
+status_t Buffer::lock(GGLSurface* sur, uint32_t usage) 
+{
+    void* vaddr;
+    status_t res = SurfaceBuffer::lock(usage, &vaddr);
+    if (res == NO_ERROR && sur) {
+        sur->version = sizeof(GGLSurface);
+        sur->width = width;
+        sur->height = height;
+        sur->stride = stride;
+        sur->format = format;
+        sur->vstride = mVStride;
+        sur->data = static_cast<GGLubyte*>(vaddr);
+    }
+    return res;
+}
+
+
+
+// ===========================================================================
+// LayerBitmap
+// ===========================================================================
+
 
 LayerBitmap::LayerBitmap()
-    : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2)
+    : mInfo(0), mWidth(0), mHeight(0)
 {
-    memset(&mSurface, 0, sizeof(mSurface));
 }
 
 LayerBitmap::~LayerBitmap()
 {
-    mSurface.data = 0;
 }
 
-status_t LayerBitmap::init(const sp<MemoryDealer>& allocator)
+status_t LayerBitmap::init(surface_info_t* info,
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
 {
-    if (mAllocator != NULL)
+    if (info == NULL)
         return BAD_VALUE;
-    mAllocator = allocator;
+    
+    mFormat = format;
+    mFlags = flags;
+    mWidth = w;
+    mHeight = h;
+
+    mInfo = info;
+    memset(info, 0, sizeof(surface_info_t));
+    info->flags = surface_info_t::eNeedNewBuffer;
+    
+    // init the buffer, but don't trigger an allocation
+    mBuffer = new Buffer(0, 0, format, flags);
     return NO_ERROR;
 }
 
-status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, 
-        PixelFormat format, uint32_t flags)
+status_t LayerBitmap::setSize(uint32_t w, uint32_t h)
 {
-    const sp<MemoryDealer>& allocator(mAllocator);
-    if (allocator == NULL)
-        return NO_INIT;
-
-    if (UNLIKELY(w == mSurface.width && h == mSurface.height &&
-            format == mSurface.format))
-    { // same format and size, do nothing.
-        return NO_ERROR;
-    }
-
-    PixelFormatInfo info;
-    getPixelFormatInfo(format, &info);
-
-    uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED;
-    const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT
-    const uint32_t Bpp = info.bytesPerPixel;
-    uint32_t stride = (w + (alignment-1)) & ~(alignment-1);
-    stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp;
-    size_t size = info.getScanlineSize(stride) * h;
-    if (allocFlags & MemoryDealer::PAGE_ALIGNED) {
-        size_t pagesize = getpagesize();
-        size = (size + (pagesize-1)) & ~(pagesize-1);
-    }
-
-    /* FIXME: we should be able to have a h/v stride because the user of the
-     * surface might have stride limitation (for instance h/w codecs often do)
-     */
-    int32_t vstride = 0;
-
-    mAlignment = alignment;
-    mAllocFlags = allocFlags;
-    mOffset = 0;
-    if (mSize != size) {
-        // would be nice to have a reallocate() api
-        mBitsMemory.clear(); // free-memory
-        mBitsMemory = allocator->allocate(size, allocFlags);
-        mSize = size;
-    } else {
-        // don't erase memory if we didn't have to reallocate
-        flags &= ~SECURE_BITS;
-    }
-    if (mBitsMemory != 0) {
-        mOffset = mBitsMemory->offset();
-        mSurface.data = static_cast<GGLubyte*>(mBitsMemory->pointer());
-        mSurface.version = sizeof(GGLSurface);
-        mSurface.width  = w;
-        mSurface.height = h;
-        mSurface.stride = stride;
-        mSurface.vstride = vstride;
-        mSurface.format = format;
-        if (flags & SECURE_BITS)
-            clear();
-    }
-
-    if (mBitsMemory==0 || mSurface.data==0) {
-        LOGE("not enough memory for layer bitmap "
-             "size=%u (w=%d, h=%d, stride=%d, format=%d)",
-             size, int(w), int(h), int(stride), int(format));
-        allocator->dump("LayerBitmap");
-        mSurface.data = 0;
-        mSize = -1U;
-        return NO_MEMORY;
+    Mutex::Autolock _l(mLock);
+    if ((w != mWidth) || (h != mHeight)) {
+        mWidth  = w;
+        mHeight = h;
+        // this will signal the client that it needs to asks us for a new buffer
+        mInfo->flags = surface_info_t::eNeedNewBuffer;
     }
     return NO_ERROR;
 }
 
-void LayerBitmap::clear()
+sp<Buffer> LayerBitmap::allocate()
 {
-    // NOTE: this memset should not be necessary, at least for
-    // opaque surface. However, for security reasons it's better to keep it
-    // (in the case of pmem, it's possible that the memory contains old
-    // data)
-    if (mSurface.data) {
-        memset(mSurface.data, 0, mSize);
-        //if (bytesPerPixel(mSurface.format) == 4) {
-        //    android_memset32((uint32_t*)mSurface.data, 0xFF0000FF, mSize);
-        //} else  {
-        //    android_memset16((uint16_t*)mSurface.data, 0xF800, mSize);
-        //}
+    Mutex::Autolock _l(mLock);
+    sp<Buffer> buffer(mBuffer);
+    const uint32_t w = mWidth; 
+    const uint32_t h = mHeight;
+    if (w != buffer->getWidth() || h != buffer->getHeight()) {
+        surface_info_t* info = mInfo;
+        buffer = new Buffer(w, h, mFormat, mFlags);
+        status_t err = buffer->initCheck();
+        if (LIKELY(err == NO_ERROR)) {
+            info->flags  = surface_info_t::eBufferDirty;
+            info->status = NO_ERROR;
+        } else {
+            memset(info, 0, sizeof(surface_info_t));
+            info->status = NO_MEMORY;
+        }
+        mBuffer = buffer;
     }
-}
-
-status_t LayerBitmap::getInfo(surface_info_t* info) const
-{
-    if (mSurface.data == 0) {
-        memset(info, 0, sizeof(surface_info_t));
-        info->bits_offset = NO_MEMORY;
-        return NO_MEMORY;
-    }
-    info->w     = uint16_t(width());
-    info->h     = uint16_t(height());
-    info->stride= uint16_t(stride());
-    info->bpr   = uint16_t(stride() * bytesPerPixel(pixelFormat()));
-    info->format= uint8_t(pixelFormat());
-    info->flags = surface_info_t::eBufferDirty;
-    info->bits_offset = ssize_t(mOffset);
-    return NO_ERROR;
-}
-
-status_t LayerBitmap::resize(uint32_t w, uint32_t h)
-{
-    int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS);
-    return err;
-}
-
-size_t LayerBitmap::size() const
-{
-    return mSize;
-}
-
-void LayerBitmap::getBitmapSurface(copybit_image_t* img) const
-{
-    const sp<IMemoryHeap>& mh(getAllocator()->getMemoryHeap());
-    void* sbase = mh->base();
-    const GGLSurface& t(surface());
-    img->w = t.stride  ?: t.width;
-    img->h = t.vstride ?: t.height;
-    img->format = t.format;
-    img->offset = intptr_t(t.data) - intptr_t(sbase);
-    img->base = sbase;
-    img->fd = mh->heapID();
+    return buffer;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
index 9ad64c4..824e0f2 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -20,63 +20,114 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <hardware/gralloc.h>
+
 #include <utils/Atomic.h>
+
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
-#include <private/ui/SharedState.h>
+#include <ui/Surface.h>
+
 #include <pixelflinger/pixelflinger.h>
 
+#include <private/ui/SharedState.h>
+#include <private/ui/SurfaceBuffer.h>
+
 class copybit_image_t;
+struct android_native_buffer_t;
 
 namespace android {
 
 // ---------------------------------------------------------------------------
-
 class IMemory;
 class MemoryDealer;
 class LayerBitmap;
 
-// ---------------------------------------------------------------------------
+// ===========================================================================
+// Buffer
+// ===========================================================================
+
+class NativeBuffer;
+
+class Buffer : public SurfaceBuffer
+{
+public:
+    enum {
+        DONT_CLEAR  = 0x00000001,
+        GPU         = 0x00000002,
+        SECURE      = 0x00000004
+    };
+
+    // creates w * h buffer
+    Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
+
+    // return status
+    status_t initCheck() const;
+
+    uint32_t getWidth() const           { return width; }
+    uint32_t getHeight() const          { return height; }
+    uint32_t getStride() const          { return stride; }
+    uint32_t getUsage() const           { return usage; }
+    PixelFormat getPixelFormat() const  { return format; }
+    Rect getBounds() const              { return Rect(width, height); }
+    
+    status_t lock(GGLSurface* surface, uint32_t usage);
+    
+    android_native_buffer_t* getNativeBuffer() const;
+    
+private:
+    friend class LightRefBase<Buffer>;
+    Buffer(const Buffer& rhs);
+    virtual ~Buffer();
+    Buffer& operator = (const Buffer& rhs);
+    const Buffer& operator = (const Buffer& rhs) const;
+
+    status_t initSize(uint32_t w, uint32_t h);
+
+    ssize_t                 mInitCheck;
+    uint32_t                mFlags;
+    uint32_t                mVStride;
+};
+
+// ===========================================================================
+// LayerBitmap
+// ===========================================================================
 
 class LayerBitmap
 {
 public:
-
     enum {
-        // erase memory to ensure security when necessary
-        SECURE_BITS = 0x00000001
+        DONT_CLEAR  = Buffer::DONT_CLEAR,
+        GPU         = Buffer::GPU,
+        SECURE      = Buffer::SECURE
     };
+    LayerBitmap();
+    ~LayerBitmap();
 
-                LayerBitmap();
-                ~LayerBitmap();
-    status_t    init(const sp<MemoryDealer>& allocator);
+    status_t init(surface_info_t* info,
+            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
 
-    status_t    setBits(uint32_t w, uint32_t h, uint32_t alignment,
-                        PixelFormat format, uint32_t flags = 0);
-    void        clear();
+    status_t setSize(uint32_t w, uint32_t h);
 
-    status_t    getInfo(surface_info_t* info) const;
-    status_t    resize(uint32_t w, uint32_t h);
+    sp<Buffer> allocate();
 
-    const GGLSurface& surface() const   { return mSurface; }
-    Rect bounds() const                 { return Rect(width(), height()); }
-    uint32_t width() const              { return surface().width; }
-    uint32_t height() const             { return surface().height; }
-    uint32_t stride() const             { return surface().stride; }
-    PixelFormat pixelFormat() const     { return surface().format; }
-    void* serverBits() const            { return surface().data; }
-    size_t size() const;
-    const sp<MemoryDealer>& getAllocator() const { return mAllocator; }
-    void getBitmapSurface(copybit_image_t* img) const;
-
+    sp<const Buffer>  getBuffer() const { return mBuffer; }
+    sp<Buffer>        getBuffer()       { return mBuffer; }
+    
+    uint32_t getWidth() const           { return mWidth; }
+    uint32_t getHeight() const          { return mHeight; }
+    PixelFormat getPixelFormat() const  { return mBuffer->getPixelFormat(); }
+    Rect getBounds() const              { return mBuffer->getBounds(); }
+    
 private:
-    sp<MemoryDealer>        mAllocator;
-    sp<IMemory>             mBitsMemory;
-    uint32_t                mAllocFlags;
-    ssize_t                 mOffset;
-    GGLSurface              mSurface;
-    size_t                  mSize;
-    uint32_t                mAlignment;
+    surface_info_t* mInfo;
+    sp<Buffer>      mBuffer;
+    uint32_t        mWidth;
+    uint32_t        mHeight;
+    PixelFormat     mFormat;
+    uint32_t        mFlags;
+    // protects setSize() and allocate()
+    mutable Mutex   mLock;
 };
 
 }; // namespace android
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index d3e456f..3d22e3a 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -49,8 +47,7 @@
 LayerBlur::~LayerBlur()
 {
     if (mTextureName != -1U) {
-        //glDeleteTextures(1, &mTextureName);
-        deletedTextures.add(mTextureName);
+        glDeleteTextures(1, &mTextureName);
     }
 }
 
@@ -139,8 +136,9 @@
         glGenTextures(1, &mTextureName);
     }
 
-    Region::iterator iterator(clip);
-    if (iterator) {
+    Region::const_iterator it = clip.begin();
+    Region::const_iterator const end = clip.end();
+    if (it != end) {
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mTextureName);
     
@@ -201,27 +199,25 @@
             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
             glVertexPointer(2, GL_FIXED, 0, mVertices);
             glTexCoordPointer(2, GL_FIXED, 0, mVertices);
-            Rect r;
-            while (iterator.iterate(&r)) {
+            while (it != end) {
+                const Rect& r = *it++;
                 const GLint sy = fbHeight - (r.top + r.height());
                 glScissor(r.left, sy, r.width(), r.height());
                 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
             }       
         } else {
-            Region::iterator iterator(clip);
-            if (iterator) {
-                // NOTE: this is marginally faster with the software gl, because
-                // glReadPixels() reads the fb bottom-to-top, however we'll
-                // skip all the jaccobian computations.
-                Rect r;
-                GLint crop[4] = { 0, 0, w, h };
-                glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
-                y = fbHeight - (y + h);
-                while (iterator.iterate(&r)) {
-                    const GLint sy = fbHeight - (r.top + r.height());
-                    glScissor(r.left, sy, r.width(), r.height());
-                    glDrawTexiOES(x, y, 0, w, h);
-                }
+            // NOTE: this is marginally faster with the software gl, because
+            // glReadPixels() reads the fb bottom-to-top, however we'll
+            // skip all the jaccobian computations.
+            Rect r;
+            GLint crop[4] = { 0, 0, w, h };
+            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+            y = fbHeight - (y + h);
+            while (it != end) {
+                const Rect& r = *it++;
+                const GLint sy = fbHeight - (r.top + r.height());
+                glScissor(r.left, sy, r.width(), r.height());
+                glDrawTexiOES(x, y, 0, w, h);
             }
         }
     }
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index bac544a..8be91c9 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <math.h>
@@ -25,15 +23,10 @@
 #include <utils/Log.h>
 #include <utils/StopWatch.h>
 
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
 #include <ui/PixelFormat.h>
-#include <ui/EGLDisplaySurface.h>
 
 #include "LayerBuffer.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 #include "DisplayHardware/DisplayHardware.h"
 
 
@@ -55,30 +48,23 @@
 
 LayerBuffer::~LayerBuffer()
 {
-    sp<SurfaceBuffer> s(getClientSurface());
-    if (s != 0) {
-        s->disown();
-        mClientSurface.clear();
-    }
 }
 
-sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const
+void LayerBuffer::onFirstRef()
 {
-    Mutex::Autolock _l(mLock);
-    return mClientSurface.promote();
+    mSurface = new SurfaceBuffer(mFlinger, clientIndex(),
+            const_cast<LayerBuffer *>(this));
 }
 
-sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const
+sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
 {
-    sp<SurfaceBuffer> s;
-    Mutex::Autolock _l(mLock);
-    s = mClientSurface.promote();
-    if (s == 0) {
-        s = new SurfaceBuffer(clientIndex(),
-                const_cast<LayerBuffer *>(this));
-        mClientSurface = s;
-    }
-    return s;
+    return mSurface;
+}
+
+status_t LayerBuffer::ditch()
+{
+    mSurface.clear();
+    return NO_ERROR;
 }
 
 bool LayerBuffer::needsBlending() const {
@@ -192,82 +178,49 @@
 // LayerBuffer::SurfaceBuffer
 // ============================================================================
 
-LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
-: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
+LayerBuffer::SurfaceBuffer::SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
+        SurfaceID id, const sp<LayerBuffer>& owner)
+    : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
 {
 }
 
 LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
 {
     unregisterBuffers();
-    mOwner = 0;
 }
 
-status_t LayerBuffer::SurfaceBuffer::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+status_t LayerBuffer::SurfaceBuffer::registerBuffers(
+        const ISurface::BufferHeap& buffers)
 {
-    switch (code) {
-        case REGISTER_BUFFERS:
-        case UNREGISTER_BUFFERS:
-        case CREATE_OVERLAY:
-        {
-            // codes that require permission check
-            IPCThreadState* ipc = IPCThreadState::self();
-            const int pid = ipc->getCallingPid();
-            const int self_pid = getpid();
-            if (LIKELY(pid != self_pid)) {
-                // we're called from a different process, do the real check
-                if (!checkCallingPermission(
-                        String16("android.permission.ACCESS_SURFACE_FLINGER")))
-                {
-                    const int uid = ipc->getCallingUid();
-                    LOGE("Permission Denial: "
-                            "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
-                    return PERMISSION_DENIED;
-                }
-            }
-        }
-    }
-    return LayerBaseClient::Surface::onTransact(code, data, reply, flags);
-}
-
-status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
-{
-    LayerBuffer* owner(getOwner());
-    if (owner)
+    sp<LayerBuffer> owner(getOwner());
+    if (owner != 0)
         return owner->registerBuffers(buffers);
     return NO_INIT;
 }
 
 void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
 {
-    LayerBuffer* owner(getOwner());
-    if (owner)
+    sp<LayerBuffer> owner(getOwner());
+    if (owner != 0)
         owner->postBuffer(offset);
 }
 
 void LayerBuffer::SurfaceBuffer::unregisterBuffers()
 {
-    LayerBuffer* owner(getOwner());
-    if (owner)
+    sp<LayerBuffer> owner(getOwner());
+    if (owner != 0)
         owner->unregisterBuffers();
 }
 
 sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
         uint32_t w, uint32_t h, int32_t format) {
     sp<OverlayRef> result;
-    LayerBuffer* owner(getOwner());
-    if (owner)
+    sp<LayerBuffer> owner(getOwner());
+    if (owner != 0)
         result = owner->createOverlay(w, h, format);
     return result;
 }
 
-void LayerBuffer::SurfaceBuffer::disown()
-{
-    Mutex::Autolock _l(mLock);
-    mOwner = 0;
-}
-
 // ============================================================================
 // LayerBuffer::Buffer
 // ============================================================================
@@ -369,7 +322,7 @@
 LayerBuffer::BufferSource::~BufferSource()
 {    
     if (mTextureName != -1U) {
-        LayerBase::deletedTextures.add(mTextureName);
+        glDeleteTextures(1, &mTextureName);
     }
 }
 
@@ -427,125 +380,37 @@
 
 void LayerBuffer::BufferSource::onDraw(const Region& clip) const 
 {
-    sp<Buffer> buffer(getBuffer());
+    // FIXME: we should get a native buffer here 
+    /*
+    sp<Buffer> ourBbuffer(getBuffer());
     if (UNLIKELY(buffer == 0))  {
         // nothing to do, we don't have a buffer
         mLayer.clearWithOpenGL(clip);
         return;
     }
 
-    status_t err = NO_ERROR;
-    NativeBuffer src(buffer->getBuffer());
-    const Rect& transformedBounds = mLayer.getTransformedBounds();
-    const int can_use_copybit = mLayer.canUseCopybit();
-
-    if (can_use_copybit)  {
-        const int src_width  = src.crop.r - src.crop.l;
-        const int src_height = src.crop.b - src.crop.t;
-        int W = transformedBounds.width();
-        int H = transformedBounds.height();
-        if (mLayer.getOrientation() & Transform::ROT_90) {
-            int t(W); W=H; H=t;
-        }
-
-        /* With LayerBuffer, it is likely that we'll have to rescale the
-         * surface, because this is often used for video playback or
-         * camera-preview. Since we want these operation as fast as possible
-         * we make sure we can use the 2D H/W even if it doesn't support
-         * the requested scale factor, in which case we perform the scaling
-         * in several passes. */
-
-        copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine();
-        const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
-        const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
-
-        float xscale = 1.0f;
-        if (src_width > W*min)          xscale = 1.0f / min;
-        else if (src_width*mag < W)     xscale = mag;
-
-        float yscale = 1.0f;
-        if (src_height > H*min)         yscale = 1.0f / min;
-        else if (src_height*mag < H)    yscale = mag;
-
-        if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
-            if (UNLIKELY(mTemporaryDealer == 0)) {
-                // allocate a memory-dealer for this the first time
-                mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager()
-                    ->createHeap(ISurfaceComposer::eHardware);
-                mTempBitmap.init(mTemporaryDealer);
-            }
-
-            const int tmp_w = floorf(src_width  * xscale);
-            const int tmp_h = floorf(src_height * yscale);
-            err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format);
-
-            if (LIKELY(err == NO_ERROR)) {
-                NativeBuffer tmp;
-                mTempBitmap.getBitmapSurface(&tmp.img);
-                tmp.crop.l = 0;
-                tmp.crop.t = 0;
-                tmp.crop.r = tmp.img.w;
-                tmp.crop.b = tmp.img.h;
-
-                region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
-                copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-                copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
-                copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
-                err = copybit->stretch(copybit,
-                        &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
-                src = tmp;
-            }
-        }
-
-        const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware());
-        copybit_image_t dst;
-        hw.getDisplaySurface(&dst);
-        const copybit_rect_t& drect
-            = reinterpret_cast<const copybit_rect_t&>(transformedBounds);
-        const State& s(mLayer.drawingState());
-        region_iterator it(clip);
-        
-        // pick the right orientation for this buffer
-        int orientation = mLayer.getOrientation();
-        if (UNLIKELY(mBufferHeap.transform)) {
-            Transform rot90;
-            GraphicPlane::orientationToTransfrom(
-                    ISurfaceComposer::eOrientation90, 0, 0, &rot90);
-            const Transform& planeTransform(mLayer.graphicPlane(0).transform());
-            const Layer::State& s(mLayer.drawingState());
-            Transform tr(planeTransform * s.transform * rot90);
-            orientation = tr.getOrientation();
-        }
-        
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
-        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
-        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-
-        err = copybit->stretch(copybit,
-                &dst, &src.img, &drect, &src.crop, &it);
-        if (err != NO_ERROR) {
-            LOGE("copybit failed (%s)", strerror(err));
-        }
+    // FIXME: We should model this after the overlay stuff
+    if (UNLIKELY(mTextureName == -1LU)) {
+        mTextureName = mLayer.createTexture();
     }
 
-    if (!can_use_copybit || err) {
-        if (UNLIKELY(mTextureName == -1LU)) {
-            mTextureName = mLayer.createTexture();
-        }
+    // FIXME: Use EGLImage extension for this
+    
+    
+    
+    GGLSurface t;
+    status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY);
+    if (res == NO_ERROR) {
         GLuint w = 0;
         GLuint h = 0;
-        GGLSurface t;
-        t.version = sizeof(GGLSurface);
-        t.width  = src.crop.r;
-        t.height = src.crop.b;
-        t.stride = src.img.w;
-        t.vstride= src.img.h;
-        t.format = src.img.format;
-        t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
-        const Region dirty(Rect(t.width, t.height));
+        const Region dirty(Rect(buffer->width, buffer->height));
         mLayer.loadTexture(dirty, mTextureName, t, w, h);
-        mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
+        buffer->unlock();
     }
+    if (res == NO_ERROR) {
+        mLayer.drawWithOpenGL(clip, mTextureName, buffer, mBufferHeap.transform);
+    }
+    */
 }
 
 
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index f74d6a1..22af43e 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -22,7 +22,6 @@
 
 #include <binder/IMemory.h>
 #include <private/ui/LayerState.h>
-#include <EGL/eglnatives.h>
 
 #include "LayerBase.h"
 #include "LayerBitmap.h"
@@ -51,7 +50,6 @@
         LayerBuffer& mLayer;
     };
 
-
 public:
     static const uint32_t typeInfo;
     static const char* const typeID;
@@ -62,9 +60,11 @@
                         Client* client, int32_t i);
         virtual ~LayerBuffer();
 
+    virtual void onFirstRef();
     virtual bool needsBlending() const;
 
-    virtual sp<LayerBaseClient::Surface> getSurface() const;
+    virtual sp<LayerBaseClient::Surface> createSurface() const;
+    virtual status_t ditch();
     virtual void onDraw(const Region& clip) const;
     virtual uint32_t doTransaction(uint32_t flags);
     virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
@@ -126,8 +126,7 @@
         status_t        mStatus;
         ISurface::BufferHeap mBufferHeap;
         size_t          mBufferSize;
-        mutable sp<MemoryDealer> mTemporaryDealer;
-        mutable LayerBitmap mTempBitmap;
+        mutable sp<android::Buffer>  mTempBitmap;
         mutable GLuint  mTextureName;
     };
     
@@ -179,34 +178,27 @@
     class SurfaceBuffer : public LayerBaseClient::Surface
     {
     public:
-                SurfaceBuffer(SurfaceID id, LayerBuffer* owner);
+                SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
+                        SurfaceID id, const sp<LayerBuffer>& owner);
         virtual ~SurfaceBuffer();
-        virtual status_t onTransact(
-            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+
         virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
+        
         virtual sp<OverlayRef> createOverlay(
                 uint32_t w, uint32_t h, int32_t format);
-       void disown();
     private:
-        LayerBuffer* getOwner() const {
-            Mutex::Autolock _l(mLock);
-            return mOwner;
+        sp<LayerBuffer> getOwner() const {
+            return static_cast<LayerBuffer*>(Surface::getOwner().get());
         }
-        mutable Mutex   mLock;
-        LayerBuffer*    mOwner;
     };
-
-    friend class SurfaceFlinger;
-    sp<SurfaceBuffer>   getClientSurface() const;
-
+    
     mutable Mutex   mLock;
     sp<Source>      mSource;
-
+    sp<Surface>     mSurface;
     bool            mInvalidate;
     bool            mNeedsBlending;
-    mutable wp<SurfaceBuffer> mClientSurface;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 0c347cc..c1e8ad6 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -25,7 +23,6 @@
 
 #include "LayerDim.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 #include "DisplayHardware/DisplayHardware.h"
 
 namespace android {
@@ -33,8 +30,6 @@
 
 const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10;
 const char* const LayerDim::typeID = "LayerDim";
-sp<MemoryDealer> LayerDim::mDimmerDealer;
-LayerBitmap LayerDim::mDimmerBitmap;
 
 // ---------------------------------------------------------------------------
 
@@ -46,14 +41,6 @@
 
 void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
 {
-    // must only be called once.
-    mDimmerDealer = flinger->getSurfaceHeapManager()
-            ->createHeap(ISurfaceComposer::eHardware);
-    if (mDimmerDealer != 0) {
-        mDimmerBitmap.init(mDimmerDealer);
-        mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565);
-        mDimmerBitmap.clear();
-    }
 }
 
 LayerDim::~LayerDim()
@@ -62,48 +49,26 @@
 
 void LayerDim::onDraw(const Region& clip) const
 {
+    // FIXME: on some h/w (like msm7K, it will be faster to use a texture)
+    
     const State& s(drawingState());
-
-    Region::iterator iterator(clip);
-    if (s.alpha>0 && iterator) {
+    Region::const_iterator it = clip.begin();
+    Region::const_iterator const end = clip.end();
+    if (s.alpha>0 && (it != end)) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
-
-        status_t err = NO_ERROR;
-        const int can_use_copybit = canUseCopybit();
-        if (can_use_copybit)  {
-            // StopWatch watch("copybit");
-            copybit_image_t dst;
-            hw.getDisplaySurface(&dst);
-            const copybit_rect_t& drect
-                = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
-
-            copybit_image_t src;
-            mDimmerBitmap.getBitmapSurface(&src);
-            const copybit_rect_t& srect(drect);
-
-            copybit_device_t* copybit = mFlinger->getBlitEngine();
-            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
-            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-            region_iterator it(clip);
-            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
-        }
-
-        if (!can_use_copybit || err) {
-            const GGLfixed alpha = (s.alpha << 16)/255;
-            const uint32_t fbHeight = hw.getHeight();
-            glDisable(GL_TEXTURE_2D);
-            glDisable(GL_DITHER);
-            glEnable(GL_BLEND);
-            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-            glColor4x(0, 0, 0, alpha);
-            glVertexPointer(2, GL_FIXED, 0, mVertices);
-            Rect r;
-            while (iterator.iterate(&r)) {
-                const GLint sy = fbHeight - (r.top + r.height());
-                glScissor(r.left, sy, r.width(), r.height());
-                glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
-            }
+        const GGLfixed alpha = (s.alpha << 16)/255;
+        const uint32_t fbHeight = hw.getHeight();
+        glDisable(GL_TEXTURE_2D);
+        glDisable(GL_DITHER);
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+        glColor4x(0, 0, 0, alpha);
+        glVertexPointer(2, GL_FIXED, 0, mVertices);
+        while (it != end) {
+            const Rect& r = *it++;
+            const GLint sy = fbHeight - (r.top + r.height());
+            glScissor(r.left, sy, r.width(), r.height());
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
         }
     }
 }
diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h
index 3e37a47..0d5bb98 100644
--- a/libs/surfaceflinger/LayerDim.h
+++ b/libs/surfaceflinger/LayerDim.h
@@ -44,10 +44,6 @@
     virtual bool isSecure() const       { return false; }
 
     static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h);
-
-private:
-    static sp<MemoryDealer> mDimmerDealer;
-    static LayerBitmap mDimmerBitmap;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerScreenshot.cpp b/libs/surfaceflinger/LayerScreenshot.cpp
deleted file mode 100644
index fb7b585..0000000
--- a/libs/surfaceflinger/LayerScreenshot.cpp
+++ /dev/null
@@ -1,110 +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.
- */
-
-#define LOG_TAG "SurfaceFlinger"
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <core/SkBitmap.h>
-
-#include <ui/EGLDisplaySurface.h>
-
-#include "LayerBase.h"
-#include "LayerScreenshot.h"
-#include "SurfaceFlinger.h"
-#include "DisplayHardware/DisplayHardware.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-const uint32_t LayerScreenshot::typeInfo = LayerBase::typeInfo | 0x20;
-const char* const LayerScreenshot::typeID = "LayerScreenshot";
-
-// ---------------------------------------------------------------------------
-
-LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, DisplayID display)
-    : LayerBase(flinger, display), mReply(0)
-{
-}
-
-LayerScreenshot::~LayerScreenshot()
-{
-}
-
-void LayerScreenshot::onDraw(const Region& clip) const
-{
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    copybit_image_t dst;
-    hw.getDisplaySurface(&dst);
-    if (dst.base != 0) {
-        uint8_t const* src = (uint8_t const*)(intptr_t(dst.base) + dst.offset); 
-        const int fbWidth = dst.w;
-        const int fbHeight = dst.h;
-        const int fbFormat = dst.format;
-
-        int x = mTransformedBounds.left;
-        int y = mTransformedBounds.top;
-        int w = mTransformedBounds.width();
-        int h = mTransformedBounds.height();
-        Parcel* const reply = mReply;
-        if (reply) {
-            const size_t Bpp = bytesPerPixel(fbFormat);
-            const size_t size = w * h * Bpp;
-            int32_t cfg = SkBitmap::kNo_Config;
-            switch (fbFormat) {
-                case PIXEL_FORMAT_RGBA_4444: cfg = SkBitmap::kARGB_4444_Config; break;
-                case PIXEL_FORMAT_RGBA_8888: cfg = SkBitmap::kARGB_8888_Config; break;
-                case PIXEL_FORMAT_RGB_565:   cfg = SkBitmap::kRGB_565_Config; break;
-                case PIXEL_FORMAT_A_8:       cfg = SkBitmap::kA8_Config; break;
-            }
-            reply->writeInt32(0);
-            reply->writeInt32(cfg);
-            reply->writeInt32(w);
-            reply->writeInt32(h);
-            reply->writeInt32(w * Bpp);
-            void* data = reply->writeInplace(size);
-            if (data) {
-                uint8_t* d = (uint8_t*)data;
-                uint8_t const* s = src + (x + y*fbWidth) * Bpp;
-                if (w == fbWidth) {
-                    memcpy(d, s, w*h*Bpp);   
-                } else {
-                    for (int y=0 ; y<h ; y++) {
-                        memcpy(d, s, w*Bpp);
-                        d += w*Bpp;
-                        s += fbWidth*Bpp;
-                    }
-                }
-            }
-        }
-    }
-    mCV.broadcast();
-}
-
-void LayerScreenshot::takeScreenshot(Mutex& lock, Parcel* reply)
-{
-    mReply = reply;
-    mCV.wait(lock);
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp
new file mode 100644
index 0000000..a027e2b
--- /dev/null
+++ b/libs/surfaceflinger/MessageQueue.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 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 <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+
+#include "MessageQueue.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+void MessageList::insert(const sp<MessageBase>& node) 
+{
+    LIST::iterator cur(mList.begin());
+    LIST::iterator end(mList.end());
+    while (cur != end) {
+        if (*node < **cur) {
+            mList.insert(cur, node);
+            return;
+        }
+        ++cur;
+    }
+    mList.insert(++end, node);
+}
+
+void MessageList::remove(MessageList::LIST::iterator pos) 
+{
+    mList.erase(pos);
+}
+
+// ---------------------------------------------------------------------------
+
+MessageQueue::MessageQueue()
+{
+    mInvalidateMessage = new MessageBase(INVALIDATE);
+}
+
+MessageQueue::~MessageQueue()
+{
+}
+
+MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout)
+{
+    MessageList::value_type result;
+
+    bool again;
+    do {
+        const nsecs_t timeoutTime = systemTime() + timeout;
+        while (true) {
+            Mutex::Autolock _l(mLock);
+            nsecs_t now = systemTime();
+            nsecs_t nextEventTime = -1;
+
+            // invalidate messages are always handled first
+            if (mInvalidate) {
+                mInvalidate = false;
+                mInvalidateMessage->when = now;
+                result = mInvalidateMessage;
+                break;
+            }
+
+            LIST::iterator cur(mMessages.begin());
+            if (cur != mMessages.end()) {
+                result = *cur;
+            }
+            
+            if (result != 0) {
+                if (result->when <= now) {
+                    // there is a message to deliver
+                    mMessages.remove(cur);
+                    break;
+                }
+                if (timeout>=0 && timeoutTime < now) {
+                    // we timed-out, return a NULL message
+                    result = 0;
+                    break;
+                }
+                nextEventTime = result->when;
+                result = 0;
+            }
+
+            if (timeout >= 0 && nextEventTime > 0) {
+                if (nextEventTime > timeoutTime) {
+                    nextEventTime = timeoutTime;
+                }
+            }
+
+            if (nextEventTime >= 0) {
+                //LOGD("nextEventTime = %lld ms", nextEventTime);
+                if (nextEventTime > 0) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+                    mCondition.wait(mLock, nextEventTime);
+                }
+            } else {
+                //LOGD("going to wait");
+                // we're about to wait, flush the binder command buffer
+                IPCThreadState::self()->flushCommands();
+                mCondition.wait(mLock);
+            }
+        } 
+        // here we're not holding the lock anymore
+
+        if (result == 0)
+            break;
+
+        again = result->handler();
+        if (again) {
+            // the message has been processed. release our reference to it
+            // without holding the lock.
+            result = 0;
+        }
+        
+    } while (again);
+
+    return result;
+}
+
+status_t MessageQueue::postMessage(
+        const MessageList::value_type& message, nsecs_t relTime, uint32_t flags)
+{
+    return queueMessage(message, relTime, flags);
+}
+
+status_t MessageQueue::invalidate() {
+    Mutex::Autolock _l(mLock);
+    mInvalidate = true;
+    mCondition.signal();
+    return NO_ERROR;
+}
+
+status_t MessageQueue::queueMessage(
+        const MessageList::value_type& message, nsecs_t relTime, uint32_t flags)
+{
+    Mutex::Autolock _l(mLock);
+    message->when = systemTime() + relTime;
+    mMessages.insert(message);
+    
+    //LOGD("MessageQueue::queueMessage time = %lld ms", message->when);
+    //dumpLocked(message);
+
+    mCondition.signal();
+    return NO_ERROR;
+}
+
+void MessageQueue::dump(const MessageList::value_type& message)
+{
+    Mutex::Autolock _l(mLock);
+    dumpLocked(message);
+}
+
+void MessageQueue::dumpLocked(const MessageList::value_type& message)
+{
+    LIST::const_iterator cur(mMessages.begin());
+    LIST::const_iterator end(mMessages.end());
+    int c = 0;
+    while (cur != end) {
+        const char tick = (*cur == message) ? '>' : ' ';
+        LOGD("%c %d: msg{.what=%08x, when=%lld}",
+                tick, c, (*cur)->what, (*cur)->when);
+        ++cur;
+        c++;
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h
new file mode 100644
index 0000000..dc8138d
--- /dev/null
+++ b/libs/surfaceflinger/MessageQueue.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_MESSAGE_QUEUE_H
+#define ANDROID_MESSAGE_QUEUE_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/List.h>
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class MessageBase;
+
+class MessageList 
+{
+    List< sp<MessageBase> > mList;
+    typedef List< sp<MessageBase> > LIST;
+public:
+    typedef sp<MessageBase> value_type;
+    inline LIST::iterator begin()                { return mList.begin(); }
+    inline LIST::const_iterator begin() const    { return mList.begin(); }
+    inline LIST::iterator end()                  { return mList.end(); }
+    inline LIST::const_iterator end() const      { return mList.end(); }
+    inline bool isEmpty() const { return mList.empty(); }
+    void insert(const sp<MessageBase>& node);
+    void remove(LIST::iterator pos);
+};
+
+// ============================================================================
+
+class MessageBase : 
+    public LightRefBase<MessageBase>
+{
+public:
+    nsecs_t     when;
+    uint32_t    what;
+    int32_t     arg0;    
+
+    MessageBase() : when(0), what(0), arg0(0) { }
+    MessageBase(uint32_t what, int32_t arg0=0)
+        : when(0), what(what), arg0(arg0) { }
+    
+    // return true if message has a handler
+    virtual bool handler() { return false; }
+    
+protected:
+    virtual ~MessageBase() { }
+
+private:
+    friend class LightRefBase<MessageBase>;
+};
+
+inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) {
+    return lhs.when < rhs.when;
+}
+
+// ---------------------------------------------------------------------------
+
+class MessageQueue
+{
+    typedef List< sp<MessageBase> > LIST;
+public:
+
+    // this is a work-around the multichar constant warning. A macro would
+    // work too, but would pollute the namespace.
+    template <int a, int b, int c, int d>
+    struct WHAT {
+        static const uint32_t Value = 
+            (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)|
+            (uint32_t(c&0xff)<<8)|uint32_t(d&0xff);
+    };
+    
+    MessageQueue();
+    ~MessageQueue();
+
+    // pre-defined messages
+    enum {
+        INVALIDATE = WHAT<'_','p','d','t'>::Value
+    };
+
+    MessageList::value_type waitMessage(nsecs_t timeout = -1);
+    
+    status_t postMessage(const MessageList::value_type& message, 
+            nsecs_t reltime=0, uint32_t flags = 0);
+        
+    status_t invalidate();
+    
+    void dump(const MessageList::value_type& message);
+
+private:
+    status_t queueMessage(const MessageList::value_type& message,
+            nsecs_t reltime, uint32_t flags);
+    void dumpLocked(const MessageList::value_type& message);
+    
+    Mutex           mLock;
+    Condition       mCondition;
+    MessageList     mMessages;
+    bool            mInvalidate;
+    MessageList::value_type mInvalidateMessage;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif /* ANDROID_MESSAGE_QUEUE_H */
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index efaf016..0d1be2d 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
@@ -41,26 +39,20 @@
 
 #include <ui/PixelFormat.h>
 #include <ui/DisplayInfo.h>
-#include <ui/EGLDisplaySurface.h>
 
 #include <pixelflinger/pixelflinger.h>
 #include <GLES/gl.h>
 
 #include "clz.h"
-#include "CPUGauge.h"
+#include "BufferAllocator.h"
 #include "Layer.h"
 #include "LayerBlur.h"
 #include "LayerBuffer.h"
 #include "LayerDim.h"
 #include "LayerBitmap.h"
-#include "LayerOrientationAnim.h"
-#include "OrientationAnimation.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 
 #include "DisplayHardware/DisplayHardware.h"
-#include "GPUHardware/GPUHardware.h"
-
 
 /* ideally AID_GRAPHICS would be in a semi-public header
  * or there would be a way to map a user/group name to its id
@@ -94,30 +86,30 @@
 }
 
 ssize_t SurfaceFlinger::LayerVector::indexOf(
-        LayerBase* key, size_t guess) const
+        const sp<LayerBase>& key, size_t guess) const
 {
     if (guess<size() && lookup.keyAt(guess) == key)
         return guess;
     const ssize_t i = lookup.indexOfKey(key);
     if (i>=0) {
         const size_t idx = lookup.valueAt(i);
-        LOG_ASSERT(layers[idx]==key,
+        LOGE_IF(layers[idx]!=key,
             "LayerVector[%p]: layers[%d]=%p, key=%p",
-            this, int(idx), layers[idx], key);
+            this, int(idx), layers[idx].get(), key.get());
         return idx;
     }
     return i;
 }
 
 ssize_t SurfaceFlinger::LayerVector::add(
-        LayerBase* layer,
-        Vector<LayerBase*>::compar_t cmp)
+        const sp<LayerBase>& layer,
+        Vector< sp<LayerBase> >::compar_t cmp)
 {
     size_t count = layers.size();
     ssize_t l = 0;
     ssize_t h = count-1;
     ssize_t mid;
-    LayerBase* const* a = layers.array();
+    sp<LayerBase> const* a = layers.array();
     while (l <= h) {
         mid = l + (h - l)/2;
         const int c = cmp(a+mid, &layer);
@@ -140,14 +132,14 @@
     return order;
 }
 
-ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer)
+ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer)
 {
     const ssize_t keyIndex = lookup.indexOfKey(layer);
     if (keyIndex >= 0) {
         const size_t index = lookup.valueAt(keyIndex);
-        LOG_ASSERT(layers[index]==layer,
+        LOGE_IF(layers[index]!=layer,
                 "LayerVector[%p]: layers[%u]=%p, layer=%p",
-                this, int(index), layers[index], layer);
+                this, int(index), layers[index].get(), layer.get());
         layers.removeItemsAt(index);
         lookup.removeItemsAt(keyIndex);
         const size_t count = lookup.size();
@@ -162,8 +154,8 @@
 }
 
 ssize_t SurfaceFlinger::LayerVector::reorder(
-        LayerBase* layer,
-        Vector<LayerBase*>::compar_t cmp)
+        const sp<LayerBase>& layer,
+        Vector< sp<LayerBase> >::compar_t cmp)
 {
     // XXX: it's a little lame. but oh well...
     ssize_t err = remove(layer);
@@ -181,6 +173,7 @@
     :   BnSurfaceComposer(), Thread(false),
         mTransactionFlags(0),
         mTransactionCount(0),
+        mLayersRemoved(false),
         mBootTime(systemTime()),
         mLastScheduledBroadcast(NULL),
         mVisibleRegionsDirty(false),
@@ -189,11 +182,7 @@
         mFreezeCount(0),
         mFreezeDisplayTime(0),
         mDebugRegion(0),
-        mDebugCpu(0),
-        mDebugFps(0),
         mDebugBackground(0),
-        mSyncObject(),
-        mDeplayedTransactionPending(0),
         mConsoleSignals(0),
         mSecureFrameBuffer(0)
 {
@@ -208,28 +197,16 @@
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sf.showupdates", value, "0");
     mDebugRegion = atoi(value);
-    property_get("debug.sf.showcpu", value, "0");
-    mDebugCpu = atoi(value);
     property_get("debug.sf.showbackground", value, "0");
     mDebugBackground = atoi(value);
-    property_get("debug.sf.showfps", value, "0");
-    mDebugFps = atoi(value);
 
     LOGI_IF(mDebugRegion,           "showupdates enabled");
-    LOGI_IF(mDebugCpu,              "showcpu enabled");
     LOGI_IF(mDebugBackground,       "showbackground enabled");
-    LOGI_IF(mDebugFps,              "showfps enabled");
 }
 
 SurfaceFlinger::~SurfaceFlinger()
 {
     glDeleteTextures(1, &mWormholeTexName);
-    delete mOrientationAnimation;
-}
-
-copybit_device_t* SurfaceFlinger::getBlitEngine() const
-{
-    return graphicPlane(0).displayHardware().getBlitEngine();
 }
 
 overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
@@ -242,26 +219,6 @@
     return mServerCblkMemory;
 }
 
-status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback,
-        gpu_info_t* gpu)
-{
-    if (mGPU == 0)
-        return INVALID_OPERATION;
-
-    IPCThreadState* ipc = IPCThreadState::self();
-    const int pid = ipc->getCallingPid();
-    status_t err = mGPU->request(pid, callback, gpu);
-    return err;
-}
-
-status_t SurfaceFlinger::revokeGPU()
-{
-    if (mGPU == 0)
-        return INVALID_OPERATION;
-
-    return mGPU->friendlyRevoke();
-}
-
 sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
 {
     Mutex::Autolock _l(mStateLock);
@@ -289,11 +246,13 @@
     Client* const client = mClientsMap.valueFor(cid);
     if (client) {
         // free all the layers this client owns
-        const Vector<LayerBaseClient*>& layers = client->getLayers();
+        Vector< wp<LayerBaseClient> > layers(client->getLayers());
         const size_t count = layers.size();
         for (size_t i=0 ; i<count ; i++) {
-            LayerBaseClient* const layer = layers[i];
-            removeLayer_l(layer);
+            sp<LayerBaseClient> layer(layers[i].promote());
+            if (layer != 0) {
+                purgatorizeLayer_l(layer);
+            }
         }
 
         // the resources associated with this client will be freed
@@ -345,9 +304,6 @@
     return (r<<11)|(g<<5)|b;
 }
 
-// this is defined in libGLES_CM.so
-extern ISurfaceComposer* GLES_localSurfaceManager;
-
 status_t SurfaceFlinger::readyToRun()
 {
     LOGI(   "SurfaceFlinger's main thread ready to run. "
@@ -364,17 +320,6 @@
     LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
     new(mServerCblk) surface_flinger_cblk_t;
 
-    // get a reference to the GPU if we have one
-    mGPU = GPUFactory::getGPU();
-
-    // create the surface Heap manager, which manages the heaps
-    // (be it in RAM or VRAM) where surfaces are allocated
-    // We give 8 MB per client.
-    mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20);
-
-    
-    GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this);
-
     // we only support one display currently
     int dpy = 0;
 
@@ -451,13 +396,6 @@
      *  We're now ready to accept clients...
      */
 
-    mOrientationAnimation = new OrientationAnimation(this);
-    
-    // start CPU gauge display
-    if (mDebugCpu)
-        mCpuGauge = new CPUGauge(this, ms2ns(500));
-
-    
     // start boot animation
     property_set("ctl.start", "bootanim");
     
@@ -472,45 +410,53 @@
 
 void SurfaceFlinger::waitForEvent()
 {
-    // wait for something to do
-    if (UNLIKELY(isFrozen())) {
-        // wait 5 seconds
-        const nsecs_t freezeDisplayTimeout = ms2ns(5000);
-        const nsecs_t now = systemTime();
-        if (mFreezeDisplayTime == 0) {
-            mFreezeDisplayTime = now;
+    while (true) {
+        nsecs_t timeout = -1;
+        if (UNLIKELY(isFrozen())) {
+            // wait 5 seconds
+            const nsecs_t freezeDisplayTimeout = ms2ns(5000);
+            const nsecs_t now = systemTime();
+            if (mFreezeDisplayTime == 0) {
+                mFreezeDisplayTime = now;
+            }
+            nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
+            timeout = waitTime>0 ? waitTime : 0;
         }
-        nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
-        int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT;
-        if (err != NO_ERROR) {
+
+        MessageList::value_type msg = mEventQueue.waitMessage(timeout);
+        if (msg != 0) {
+            mFreezeDisplayTime = 0;
+            switch (msg->what) {
+                case MessageQueue::INVALIDATE:
+                    // invalidate message, just return to the main loop
+                    return;
+            }
+        } else {
+            // we timed out
             if (isFrozen()) {
                 // we timed out and are still frozen
                 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
                         mFreezeDisplay, mFreezeCount);
                 mFreezeCount = 0;
                 mFreezeDisplay = false;
+                return;
             }
         }
-    } else {
-        mFreezeDisplayTime = 0;
-        mSyncObject.wait();
     }
 }
 
 void SurfaceFlinger::signalEvent() {
-    mSyncObject.open();
+    mEventQueue.invalidate();
 }
 
 void SurfaceFlinger::signal() const {
-    mSyncObject.open();
+    // this is the IPC call
+    const_cast<SurfaceFlinger*>(this)->signalEvent();
 }
 
 void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
 {
-    if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) {
-        sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay));
-        delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY);
-    }
+    mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay);
 }
 
 // ----------------------------------------------------------------------------
@@ -549,11 +495,6 @@
         unlockClients();
         executeScheduledBroadcasts();
 
-        // sample the cpu gauge
-        if (UNLIKELY(mDebugCpu)) {
-            handleDebugCpu();
-        }
-
         postFramebuffer();
     } else {
         // pretend we did the post
@@ -566,28 +507,18 @@
 
 void SurfaceFlinger::postFramebuffer()
 {
-    const bool skip = mOrientationAnimation->run();
-    if (UNLIKELY(skip)) {
+    if (isFrozen()) {
+        // we are not allowed to draw, but pause a bit to make sure
+        // apps don't end up using the whole CPU, if they depend on
+        // surfaceflinger for synchronization.
+        usleep(8333); // 8.3ms ~ 120fps
         return;
     }
 
     if (!mInvalidRegion.isEmpty()) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
-
-        if (UNLIKELY(mDebugFps)) {
-            debugShowFPS();
-        }
-
         hw.flip(mInvalidRegion);
-
         mInvalidRegion.clear();
-
-        if (Layer::deletedTextures.size()) {
-            glDeleteTextures(
-                    Layer::deletedTextures.size(),
-                    Layer::deletedTextures.array());
-            Layer::deletedTextures.clear();
-        }
     }
 }
 
@@ -602,15 +533,13 @@
     }
 
     if (mDeferReleaseConsole && hw.canDraw()) {
-        // We got the release signal before the aquire signal
+        // We got the release signal before the acquire signal
         mDeferReleaseConsole = false;
-        revokeGPU();
         hw.releaseScreen();
     }
 
     if (what & eConsoleReleased) {
         if (hw.canDraw()) {
-            revokeGPU();
             hw.releaseScreen();
         } else {
             mDeferReleaseConsole = true;
@@ -622,9 +551,25 @@
 
 void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
 {
-    Mutex::Autolock _l(mStateLock);
+    Vector< sp<LayerBase> > ditchedLayers;
 
-    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+    { // scope for the lock
+        Mutex::Autolock _l(mStateLock);
+        handleTransactionLocked(transactionFlags, ditchedLayers);
+    }
+
+    // do this without lock held
+    const size_t count = ditchedLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        //LOGD("ditching layer %p", ditchedLayers[i].get());
+        ditchedLayers[i]->ditch();
+    }
+}
+
+void SurfaceFlinger::handleTransactionLocked(
+        uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers)
+{
+    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
     const size_t count = currentLayers.size();
 
     /*
@@ -635,7 +580,7 @@
     const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
     if (layersNeedTransaction) {
         for (size_t i=0 ; i<count ; i++) {
-            LayerBase* const layer = currentLayers[i];
+            const sp<LayerBase>& layer = currentLayers[i];
             uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
             if (!trFlags) continue;
 
@@ -682,7 +627,6 @@
             mVisibleRegionsDirty = true;
             mDirtyRegion.set(hw.bounds());
             mFreezeDisplayTime = 0;
-            mOrientationAnimation->onOrientationChanged(type);
         }
 
         if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
@@ -690,19 +634,26 @@
             mFreezeDisplay = mCurrentState.freezeDisplay;
         }
 
-        // some layers might have been removed, so
-        // we need to update the regions they're exposing.
-        size_t c = mRemovedLayers.size();
-        if (c) {
-            mVisibleRegionsDirty = true;
-        }
-
-        const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
         if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
             // layers have been added
             mVisibleRegionsDirty = true;
         }
 
+        // some layers might have been removed, so
+        // we need to update the regions they're exposing.
+        if (mLayersRemoved) {
+            mVisibleRegionsDirty = true;
+            const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
+            const size_t count = previousLayers.size();
+            for (size_t i=0 ; i<count ; i++) {
+                const sp<LayerBase>& layer(previousLayers[i]);
+                if (currentLayers.indexOf( layer ) < 0) {
+                    // this layer is not visible anymore
+                    ditchedLayers.add(layer);
+                }
+            }
+        }
+
         // get rid of all resources we don't need anymore
         // (layers and clients)
         free_resources_l();
@@ -730,7 +681,7 @@
 
     size_t i = currentLayers.size();
     while (i--) {
-        LayerBase* const layer = currentLayers[i];
+        const sp<LayerBase>& layer = currentLayers[i];
         layer->validateVisibility(planeTransform);
 
         // start with the whole surface at its current location
@@ -782,7 +733,7 @@
         // accumulate to the screen dirty region
         dirtyRegion.orSelf(dirty);
 
-        // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
+        // Update aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
         aboveOpaqueLayers.orSelf(opaqueRegion);
         aboveCoveredLayers.orSelf(bounds);
         
@@ -790,7 +741,7 @@
         layer->setVisibleRegion(visibleRegion);
         layer->setCoveredRegion(coveredRegion);
 
-        // If a secure layer is partially visible, lockdown the screen!
+        // If a secure layer is partially visible, lock down the screen!
         if (layer->isSecure() && !visibleRegion.isEmpty()) {
             secureFrameBuffer = true;
         }
@@ -830,9 +781,9 @@
 {
     bool recomputeVisibleRegions = false;
     size_t count = currentLayers.size();
-    LayerBase* const* layers = currentLayers.array();
+    sp<LayerBase> const* layers = currentLayers.array();
     for (size_t i=0 ; i<count ; i++) {
-        LayerBase* const layer = layers[i];
+        const sp<LayerBase>& layer = layers[i];
         layer->lockPageFlip(recomputeVisibleRegions);
     }
     return recomputeVisibleRegions;
@@ -843,9 +794,9 @@
     const GraphicPlane& plane(graphicPlane(0));
     const Transform& planeTransform(plane.transform());
     size_t count = currentLayers.size();
-    LayerBase* const* layers = currentLayers.array();
+    sp<LayerBase> const* layers = currentLayers.array();
     for (size_t i=0 ; i<count ; i++) {
-        LayerBase* const layer = layers[i];
+        const sp<LayerBase>& layer = layers[i];
         layer->unlockPageFlip(planeTransform, mDirtyRegion);
     }
 }
@@ -865,12 +816,14 @@
     mInvalidRegion.orSelf(mDirtyRegion);
 
     uint32_t flags = hw.getFlags();
-    if (flags & DisplayHardware::BUFFER_PRESERVED) {
-        // here we assume DisplayHardware::flip()'s  implementation
-        // performs the copy-back optimization.
+    if ((flags & DisplayHardware::SWAP_RECTANGLE) || 
+        (flags & DisplayHardware::BUFFER_PRESERVED)) 
+    {
+        // we can redraw only what's dirty
     } else {
         if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
-            // we need to fully redraw the part that will be updated
+            // we need to redraw the rectangle that will be updated
+            // (pushed to the framebuffer).
             mDirtyRegion.set(mInvalidRegion.bounds());
         } else {
             // we need to redraw everything
@@ -896,9 +849,9 @@
     const SurfaceFlinger& flinger(*this);
     const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
     const size_t count = drawingLayers.size();
-    LayerBase const* const* const layers = drawingLayers.array();
+    sp<LayerBase> const* const layers = drawingLayers.array();
     for (size_t i=0 ; i<count ; ++i) {
-        LayerBase const * const layer = layers[i];
+        const sp<LayerBase>& layer = layers[i];
         const Region& visibleRegion(layer->visibleRegionScreen);
         if (!visibleRegion.isEmpty())  {
             const Region clip(dirty.intersect(visibleRegion));
@@ -913,9 +866,9 @@
 {
     const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
     const size_t count = drawingLayers.size();
-    LayerBase* const* const layers = drawingLayers.array();
+    sp<LayerBase> const* const layers = drawingLayers.array();
     for (size_t i=0 ; i<count ; ++i) {
-        LayerBase* const layer = layers[i];
+        const sp<LayerBase>& layer = layers[i];
         layer->finishPageFlip();
     }
 }
@@ -948,32 +901,35 @@
     mLastScheduledBroadcast = 0;
 }
 
-void SurfaceFlinger::handleDebugCpu()
-{
-    Mutex::Autolock _l(mDebugLock);
-    if (mCpuGauge != 0)
-        mCpuGauge->sample();
-}
-
 void SurfaceFlinger::debugFlashRegions()
 {
-    if (UNLIKELY(!mDirtyRegion.isRect())) {
-        // TODO: do this only if we don't have preserving
-        // swapBuffer. If we don't have update-on-demand,
-        // redraw everything.
-        composeSurfaces(Region(mDirtyRegion.bounds()));
-    }
+     const DisplayHardware& hw(graphicPlane(0).displayHardware());
+     const uint32_t flags = hw.getFlags();
 
+     if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
+             (flags & DisplayHardware::BUFFER_PRESERVED))) {
+         const Region repaint((flags & DisplayHardware::UPDATE_ON_DEMAND) ?
+                 mDirtyRegion.bounds() : hw.bounds());
+         composeSurfaces(repaint);
+     }
+    
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_BLEND);
     glDisable(GL_DITHER);
     glDisable(GL_SCISSOR_TEST);
 
-    glColor4x(0x10000, 0, 0x10000, 0x10000);
+    static int toggle = 0;
+    toggle = 1 - toggle;
+    if (toggle) {
+        glColor4x(0x10000, 0, 0x10000, 0x10000);
+    } else {
+        glColor4x(0x10000, 0x10000, 0, 0x10000);
+    }
 
-    Rect r;
-    Region::iterator iterator(mDirtyRegion);
-    while (iterator.iterate(&r)) {
+    Region::const_iterator it = mDirtyRegion.begin();
+    Region::const_iterator const end = mDirtyRegion.end();
+    while (it != end) {
+        const Rect& r = *it++;
         GLfloat vertices[][2] = {
                 { r.left,  r.top },
                 { r.left,  r.bottom },
@@ -983,8 +939,7 @@
         glVertexPointer(2, GL_FLOAT, 0, vertices);
         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     }
-
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    
     hw.flip(mDirtyRegion.merge(mInvalidRegion));
     mInvalidRegion.clear();
 
@@ -1010,9 +965,10 @@
 
     if (LIKELY(!mDebugBackground)) {
         glClearColorx(0,0,0,0);
-        Rect r;
-        Region::iterator iterator(region);
-        while (iterator.iterate(&r)) {
+        Region::const_iterator it = region.begin();
+        Region::const_iterator const end = region.end();
+        while (it != end) {
+            const Rect& r = *it++;
             const GLint sy = height - (r.top + r.height());
             glScissor(r.left, sy, r.width(), r.height());
             glClear(GL_COLOR_BUFFER_BIT);
@@ -1030,9 +986,10 @@
         glMatrixMode(GL_TEXTURE);
         glLoadIdentity();
         glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
-        Rect r;
-        Region::iterator iterator(region);
-        while (iterator.iterate(&r)) {
+        Region::const_iterator it = region.begin();
+        Region::const_iterator const end = region.end();
+        while (it != end) {
+            const Rect& r = *it++;
             const GLint sy = height - (r.top + r.height());
             glScissor(r.left, sy, r.width(), r.height());
             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -1058,7 +1015,7 @@
     // XXX: mFPS has the value we want
  }
 
-status_t SurfaceFlinger::addLayer(LayerBase* layer)
+status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
 {
     Mutex::Autolock _l(mStateLock);
     addLayer_l(layer);
@@ -1066,56 +1023,69 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::removeLayer(LayerBase* layer)
+status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
 {
     Mutex::Autolock _l(mStateLock);
-    removeLayer_l(layer);
-    setTransactionFlags(eTransactionNeeded);
-    return NO_ERROR;
+    status_t err = purgatorizeLayer_l(layer);
+    if (err == NO_ERROR)
+        setTransactionFlags(eTransactionNeeded);
+    return err;
 }
 
-status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer)
+status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
 {
     layer->forceVisibilityTransaction();
     setTransactionFlags(eTraversalNeeded);
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::addLayer_l(LayerBase* layer)
+status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
 {
     ssize_t i = mCurrentState.layersSortedByZ.add(
                 layer, &LayerBase::compareCurrentStateZ);
-    LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer);
-    if (lbc) {
+    sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
+    if (lbc != 0) {
         mLayerMap.add(lbc->serverIndex(), lbc);
     }
-    mRemovedLayers.remove(layer);
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase)
+status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
 {
     ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
     if (index >= 0) {
-        mRemovedLayers.add(layerBase);
-        LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase);
-        if (layer) {
+        mLayersRemoved = true;
+        sp<LayerBaseClient> layer =
+            LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
+        if (layer != 0) {
             mLayerMap.removeItem(layer->serverIndex());
         }
         return NO_ERROR;
     }
+    return status_t(index);
+}
+
+status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
+{
+    // First add the layer to the purgatory list, which makes sure it won't 
+    // go away, then remove it from the main list (through a transaction).
+    ssize_t err = removeLayer_l(layerBase);
+    if (err >= 0) {
+        mLayerPurgatory.add(layerBase);
+    }
     // it's possible that we don't find a layer, because it might
     // have been destroyed already -- this is not technically an error
-    // from the user because there is a race between destroySurface,
-    // destroyclient and destroySurface-from-a-transaction.
-    return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index;
+    // from the user because there is a race between BClient::destroySurface(),
+    // ~BClient() and ~ISurface().
+    return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
 }
 
+
 void SurfaceFlinger::free_resources_l()
 {
     // Destroy layers that were removed
-    destroy_all_removed_layers_l();
-
+    mLayersRemoved = false;
+    
     // free resources associated with disconnected clients
     SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
     Vector<Client*>& disconnectedClients(mDisconnectedClients);
@@ -1135,22 +1105,6 @@
     disconnectedClients.clear();
 }
 
-void SurfaceFlinger::destroy_all_removed_layers_l()
-{
-    size_t c = mRemovedLayers.size();
-    while (c--) {
-        LayerBase* const removed_layer = mRemovedLayers[c];
-
-        LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0,
-            "layer %p removed but still in the current state list",
-            removed_layer);
-
-        delete removed_layer;
-    }
-    mRemovedLayers.clear();
-}
-
-
 uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
 {
     return android_atomic_and(~flags, &mTransactionFlags) & flags;
@@ -1191,7 +1145,7 @@
     setTransactionFlags(eTransactionNeeded);
 
     // flags is intended to communicate some sort of animation behavior
-    // (for instance fadding)
+    // (for instance fading)
     return NO_ERROR;
 }
 
@@ -1205,7 +1159,7 @@
     setTransactionFlags(eTransactionNeeded);
 
     // flags is intended to communicate some sort of animation behavior
-    // (for instance fadding)
+    // (for instance fading)
     return NO_ERROR;
 }
 
@@ -1234,7 +1188,7 @@
         DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
         uint32_t flags)
 {
-    LayerBaseClient* layer = 0;
+    sp<LayerBaseClient> layer;
     sp<LayerBaseClient::Surface> surfaceHandle;
     Mutex::Autolock _l(mStateLock);
     Client* const c = mClientsMap.valueFor(clientId);
@@ -1266,7 +1220,7 @@
             break;
     }
 
-    if (layer) {
+    if (layer != 0) {
         setTransactionFlags(eTransactionNeeded);
         surfaceHandle = layer->getSurface();
         if (surfaceHandle != 0)
@@ -1276,7 +1230,7 @@
     return surfaceHandle;
 }
 
-LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
+sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
         Client* client, DisplayID display,
         int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
 {
@@ -1291,57 +1245,109 @@
         break;
     }
 
-    Layer* layer = new Layer(this, display, client, id);
+    sp<Layer> layer = new Layer(this, display, client, id);
     status_t err = layer->setBuffers(client, w, h, format, flags);
     if (LIKELY(err == NO_ERROR)) {
         layer->initStates(w, h, flags);
         addLayer_l(layer);
     } else {
         LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
-        delete layer;
-        return 0;
+        layer.clear();
     }
     return layer;
 }
 
-LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked(
+sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
         Client* client, DisplayID display,
         int32_t id, uint32_t w, uint32_t h, uint32_t flags)
 {
-    LayerBlur* layer = new LayerBlur(this, display, client, id);
+    sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
     layer->initStates(w, h, flags);
     addLayer_l(layer);
     return layer;
 }
 
-LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked(
+sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
         Client* client, DisplayID display,
         int32_t id, uint32_t w, uint32_t h, uint32_t flags)
 {
-    LayerDim* layer = new LayerDim(this, display, client, id);
+    sp<LayerDim> layer = new LayerDim(this, display, client, id);
     layer->initStates(w, h, flags);
     addLayer_l(layer);
     return layer;
 }
 
-LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked(
+sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
         Client* client, DisplayID display,
         int32_t id, uint32_t w, uint32_t h, uint32_t flags)
 {
-    LayerBuffer* layer = new LayerBuffer(this, display, client, id);
+    sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id);
     layer->initStates(w, h, flags);
     addLayer_l(layer);
     return layer;
 }
 
-status_t SurfaceFlinger::destroySurface(SurfaceID index)
+status_t SurfaceFlinger::removeSurface(SurfaceID index)
 {
+    /*
+     * called by the window manager, when a surface should be marked for
+     * destruction.
+     * 
+     * The surface is removed from the current and drawing lists, but placed
+     * in the purgatory queue, so it's not destroyed right-away (we need
+     * to wait for all client's references to go away first).
+     */
+
     Mutex::Autolock _l(mStateLock);
-    LayerBaseClient* const layer = getLayerUser_l(index);
-    status_t err = removeLayer_l(layer);
-    if (err < 0)
-        return err;
-    setTransactionFlags(eTransactionNeeded);
+    sp<LayerBaseClient> layer = getLayerUser_l(index);
+    status_t err = purgatorizeLayer_l(layer);
+    if (err == NO_ERROR) {
+        setTransactionFlags(eTransactionNeeded);
+    }
+    return err;
+}
+
+status_t SurfaceFlinger::destroySurface(const sp<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() {
+            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(layer);
+            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(layer);
+                LOGE_IF(idx < 0,
+                        "layer=%p is not in the purgatory list", layer.get());
+            }
+            return true;
+        }
+    };
+
+    // It's better to not acquire our internal lock here, because it's hard
+    // to predict that it's not going to be already taken when ~Surface()
+    // is called.
+
+    mEventQueue.postMessage( new MessageDestroySurface(this, layer) );
     return NO_ERROR;
 }
 
@@ -1355,18 +1361,9 @@
     cid <<= 16;
     for (int i=0 ; i<count ; i++) {
         const layer_state_t& s = states[i];
-        LayerBaseClient* layer = getLayerUser_l(s.surface | cid);
-        if (layer) {
+        sp<LayerBaseClient> layer(getLayerUser_l(s.surface | cid));
+        if (layer != 0) {
             const uint32_t what = s.what;
-            // check if it has been destroyed first
-            if (what & eDestroyed) {
-                if (removeLayer_l(layer) == NO_ERROR) {
-                    flags |= eTransactionNeeded;
-                    // we skip everything else... well, no, not really
-                    // we skip ONLY that transaction.
-                    continue;
-                }
-            }
             if (what & ePositionChanged) {
                 if (layer->setPosition(s.x, s.y))
                     flags |= eTraversalNeeded;
@@ -1408,9 +1405,10 @@
     return NO_ERROR;
 }
 
-LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const
+sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
 {
-    return mLayerMap.valueFor(s);
+    sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
+    return layer;
 }
 
 void SurfaceFlinger::screenReleased(int dpy)
@@ -1453,7 +1451,7 @@
         const size_t count = currentLayers.size();
         for (size_t i=0 ; i<count ; i++) {
             /*** LayerBase ***/
-            LayerBase const * const layer = currentLayers[i];
+            const sp<LayerBase>& layer = currentLayers[i];
             const Layer::State& s = layer->drawingState();
             snprintf(buffer, SIZE,
                     "+ %s %p\n"
@@ -1461,7 +1459,7 @@
                     "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
                     "needsBlending=%1d, invalidate=%1d, "
                     "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
-                    layer->getTypeID(), layer,
+                    layer->getTypeID(), layer.get(),
                     s.z, layer->tx(), layer->ty(), s.w, s.h,
                     layer->needsBlending(), layer->contentDirty,
                     s.alpha, s.flags,
@@ -1470,9 +1468,9 @@
             result.append(buffer);
             buffer[0] = 0;
             /*** LayerBaseClient ***/
-            LayerBaseClient* const lbc =
-                LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer);
-            if (lbc) {
+            sp<LayerBaseClient> lbc =
+                LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
+            if (lbc != 0) {
                 snprintf(buffer, SIZE,
                         "      "
                         "id=0x%08x, client=0x%08x, identity=%u\n",
@@ -1482,18 +1480,20 @@
             result.append(buffer);
             buffer[0] = 0;
             /*** Layer ***/
-            Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer);
-            if (l) {
+            sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
+            if (l != 0) {
                 const LayerBitmap& buf0(l->getBuffer(0));
                 const LayerBitmap& buf1(l->getBuffer(1));
                 snprintf(buffer, SIZE,
                         "      "
-                        "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d,"
+                        "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
                         " freezeLock=%p, swapState=0x%08x\n",
                         l->pixelFormat(),
-                        buf0.width(), buf0.height(), buf0.stride(),
-                        buf1.width(), buf1.height(), buf1.stride(),
-                        l->getTextureName(), l->getFreezeLock().get(),
+                        buf0.getWidth(), buf0.getHeight(), 
+                        buf0.getBuffer()->getStride(),
+                        buf1.getWidth(), buf1.getHeight(), 
+                        buf1.getBuffer()->getStride(),
+                        l->getFreezeLock().get(),
                         l->lcblk->swapState);
             }
             result.append(buffer);
@@ -1509,20 +1509,10 @@
                 mFreezeDisplay?"yes":"no", mFreezeCount,
                 mCurrentState.orientation, hw.canDraw());
         result.append(buffer);
-
-        sp<AllocatorInterface> allocator;
-        if (mGPU != 0) {
-            snprintf(buffer, SIZE, "  GPU owner: %d\n", mGPU->getOwner());
-            result.append(buffer);
-            allocator = mGPU->getAllocator();
-            if (allocator != 0) {
-                allocator->dump(result, "GPU Allocator");
-            }
-        }
-        allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM);
-        if (allocator != 0) {
-            allocator->dump(result, "PMEM Allocator");
-        }
+        snprintf(buffer, SIZE, "  purgatory size: %d\n", mLayerPurgatory.size());
+        result.append(buffer);
+        const BufferAllocator& alloc(BufferAllocator::get());
+        alloc.dump(result);
     }
     write(fd, result.string(), result.size());
     return NO_ERROR;
@@ -1539,7 +1529,6 @@
         case FREEZE_DISPLAY:
         case UNFREEZE_DISPLAY:
         case BOOT_FINISHED:
-        case REVOKE_GPU:
         {
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
@@ -1572,24 +1561,9 @@
         }
         int n;
         switch (code) {
-            case 1000: // SHOW_CPU
-                n = data.readInt32();
-                mDebugCpu = n ? 1 : 0;
-                if (mDebugCpu) {
-                    if (mCpuGauge == 0) {
-                        mCpuGauge = new CPUGauge(this, ms2ns(500));
-                    }
-                } else {
-                    if (mCpuGauge != 0) {
-                        mCpuGauge->requestExitAndWait();
-                        Mutex::Autolock _l(mDebugLock);
-                        mCpuGauge.clear();
-                    }
-                }
+            case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
                 return NO_ERROR;
-            case 1001:  // SHOW_FPS
-                n = data.readInt32();
-                mDebugFps = n ? 1 : 0;
+            case 1001:  // SHOW_FPS, NOT SUPPORTED ANYMORE
                 return NO_ERROR;
             case 1002:  // SHOW_UPDATES
                 n = data.readInt32();
@@ -1606,21 +1580,11 @@
                 signalEvent();
             }
             return NO_ERROR;
-            case 1005: // ask GPU revoke
-                if (mGPU != 0) {
-                    mGPU->friendlyRevoke();
-                }
-                return NO_ERROR;
-            case 1006: // revoke GPU
-                if (mGPU != 0) {
-                    mGPU->unconditionalRevoke();
-                }
-                return NO_ERROR;
             case 1007: // set mFreezeCount
                 mFreezeCount = data.readInt32();
                 return NO_ERROR;
             case 1010:  // interrogate.
-                reply->writeInt32(mDebugCpu);
+                reply->writeInt32(0);
                 reply->writeInt32(0);
                 reply->writeInt32(mDebugRegion);
                 reply->writeInt32(mDebugBackground);
@@ -1644,7 +1608,6 @@
 Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
     : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
 {
-    mSharedHeapAllocator = getSurfaceHeapManager()->createHeap();
     const int pgsize = getpagesize();
     const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
     mCblkHeap = new MemoryDealer(cblksize);
@@ -1664,10 +1627,6 @@
     }
 }
 
-const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const {
-    return mFlinger->getSurfaceHeapManager();
-}
-
 int32_t Client::generateId(int pid)
 {
     const uint32_t i = clz( ~mBitmap );
@@ -1679,13 +1638,15 @@
     mBitmap |= 1<<(31-i);
     return i;
 }
-status_t Client::bindLayer(LayerBaseClient* layer, int32_t id)
+
+status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id)
 {
     ssize_t idx = mInUse.indexOf(id);
     if (idx < 0)
         return NAME_NOT_FOUND;
     return mLayers.insertAt(layer, idx);
 }
+
 void Client::free(int32_t id)
 {
     ssize_t idx = mInUse.remove(uint8_t(id));
@@ -1695,27 +1656,18 @@
     }
 }
 
-sp<MemoryDealer> Client::createAllocator(uint32_t flags)
-{
-    sp<MemoryDealer> allocator;
-    allocator = getSurfaceHeapManager()->createHeap(
-            flags, getClientPid(), mSharedHeapAllocator);
-    return allocator;
-}
-
 bool Client::isValid(int32_t i) const {
     return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
 }
-const uint8_t* Client::inUseArray() const {
-    return mInUse.array();
-}
-size_t Client::numActiveLayers() const {
-    return mInUse.size();
-}
-LayerBaseClient* Client::getLayerUser(int32_t i) const {
+
+sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
+    sp<LayerBaseClient> lbc;
     ssize_t idx = mInUse.indexOf(uint8_t(i));
-    if (idx<0) return 0;
-    return mLayers[idx];
+    if (idx >= 0) {
+        lbc = mLayers[idx].promote();
+        LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx));
+    }
+    return lbc;
 }
 
 void Client::dump(const char* what)
@@ -1752,7 +1704,7 @@
 status_t BClient::destroySurface(SurfaceID sid)
 {
     sid |= (mId << 16); // add the client-part to id
-    return mFlinger->destroySurface(sid);
+    return mFlinger->removeSurface(sid);
 }
 
 status_t BClient::setState(int32_t count, const layer_state_t* states)
@@ -1852,6 +1804,10 @@
     return mGlobalTransform;
 }
 
+EGLDisplay GraphicPlane::getEGLDisplay() const {
+    return mHw->getEGLDisplay();
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 126bce8..a21e186 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -26,6 +26,7 @@
 #include <utils/Atomic.h>
 #include <utils/Errors.h>
 #include <binder/MemoryDealer.h>
+#include <utils/RefBase.h>
 
 #include <ui/PixelFormat.h>
 #include <ui/ISurfaceComposer.h>
@@ -33,13 +34,13 @@
 
 #include <private/ui/SharedState.h>
 #include <private/ui/LayerState.h>
-#include <private/ui/SurfaceFlingerSynchro.h>
 
 #include "Barrier.h"
-#include "CPUGauge.h"
 #include "Layer.h"
 #include "Tokenizer.h"
 
+#include "MessageQueue.h"
+
 struct copybit_device_t;
 struct overlay_device_t;
 
@@ -51,13 +52,8 @@
 class BClient;
 class DisplayHardware;
 class FreezeLock;
-class GPUHardwareInterface;
-class IGPUCallback;
 class Layer;
 class LayerBuffer;
-class LayerOrientationAnim;
-class OrientationAnimation;
-class SurfaceHeapManager;
 
 typedef int32_t ClientID;
 
@@ -74,17 +70,13 @@
 
             int32_t                 generateId(int pid);
             void                    free(int32_t id);
-            status_t                bindLayer(LayerBaseClient* layer, int32_t id);
-            sp<MemoryDealer>        createAllocator(uint32_t memory_type);
+            status_t                bindLayer(const sp<LayerBaseClient>& layer, int32_t id);
 
     inline  bool                    isValid(int32_t i) const;
-    inline  const uint8_t*          inUseArray() const;
-    inline  size_t                  numActiveLayers() const;
-    LayerBaseClient*                getLayerUser(int32_t i) const;
-    const Vector<LayerBaseClient*>& getLayers() const { return mLayers; }
+    sp<LayerBaseClient>             getLayerUser(int32_t i) const;
+    const Vector< wp<LayerBaseClient> >& getLayers() const { return mLayers; }
     const sp<IMemory>&              controlBlockMemory() const { return mCblkMemory; }
     void                            dump(const char* what);
-    const sp<SurfaceHeapManager>&   getSurfaceHeapManager() const;
     
     // pointer to this client's control block
     per_client_cblk_t*      ctrlblk;
@@ -94,15 +86,13 @@
 private:
     int                     getClientPid() const { return mPid; }
         
-    int                         mPid;
-    uint32_t                    mBitmap;
-    SortedVector<uint8_t>       mInUse;
-    Vector<LayerBaseClient*>    mLayers;
-    sp<MemoryDealer>            mCblkHeap;
-    sp<SurfaceFlinger>          mFlinger;
-    sp<MemoryDealer>            mSharedHeapAllocator;
-    sp<MemoryDealer>            mPMemAllocator;
-    sp<IMemory>                 mCblkMemory;
+    int                             mPid;
+    uint32_t                        mBitmap;
+    SortedVector<uint8_t>           mInUse;
+    Vector< wp<LayerBaseClient> >   mLayers;
+    sp<MemoryDealer>                mCblkHeap;
+    sp<SurfaceFlinger>              mFlinger;
+    sp<IMemory>                     mCblkMemory;
 };
 
 // ---------------------------------------------------------------------------
@@ -125,6 +115,8 @@
 
         const DisplayHardware&  displayHardware() const;
         const Transform&        transform() const;
+        EGLDisplay              getEGLDisplay() const;
+        
 private:
                                 GraphicPlane(const GraphicPlane&);
         GraphicPlane            operator = (const GraphicPlane&);
@@ -168,28 +160,16 @@
     virtual status_t                    unfreezeDisplay(DisplayID dpy, uint32_t flags);
     virtual int                         setOrientation(DisplayID dpy, int orientation, uint32_t flags);
     virtual void                        signal() const;
-    virtual status_t requestGPU(const sp<IGPUCallback>& callback, 
-            gpu_info_t* gpu);
-    virtual status_t revokeGPU();
 
             void                        screenReleased(DisplayID dpy);
             void                        screenAcquired(DisplayID dpy);
 
-            const sp<SurfaceHeapManager>& getSurfaceHeapManager() const { 
-                return mSurfaceHeapManager; 
-            }
-
-            const sp<GPUHardwareInterface>& getGPU() const {
-                return mGPU; 
-            }
-
-            copybit_device_t* getBlitEngine() const;
             overlay_control_device_t* getOverlayEngine() const;
 
             
-    status_t removeLayer(LayerBase* layer);
-    status_t addLayer(LayerBase* layer);
-    status_t invalidateLayerVisibility(LayerBase* layer);
+    status_t removeLayer(const sp<LayerBase>& layer);
+    status_t addLayer(const sp<LayerBase>& layer);
+    status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
     
 private:
     friend class BClient;
@@ -204,20 +184,26 @@
             DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
             uint32_t flags);
 
-    LayerBaseClient* createNormalSurfaceLocked(Client* client, DisplayID display,
-            int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+    sp<LayerBaseClient> createNormalSurfaceLocked(
+            Client* client, DisplayID display,
+            int32_t id, uint32_t w, uint32_t h, 
+            PixelFormat format, uint32_t flags);
 
-    LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display,
+    sp<LayerBaseClient> createBlurSurfaceLocked(
+            Client* client, DisplayID display,
             int32_t id, uint32_t w, uint32_t h, uint32_t flags);
 
-    LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display,
+    sp<LayerBaseClient> createDimSurfaceLocked(
+            Client* client, DisplayID display,
             int32_t id, uint32_t w, uint32_t h, uint32_t flags);
 
-    LayerBaseClient* createPushBuffersSurfaceLocked(Client* client, DisplayID display,
+    sp<LayerBaseClient> createPushBuffersSurfaceLocked(
+            Client* client, DisplayID display,
             int32_t id, uint32_t w, uint32_t h, uint32_t flags);
 
-    status_t    destroySurface(SurfaceID surface_id);
-    status_t    setClientState(ClientID cid, int32_t count, const layer_state_t* states);
+    status_t removeSurface(SurfaceID surface_id);
+    status_t destroySurface(const sp<LayerBaseClient>& layer);
+    status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states);
 
 
     class LayerVector {
@@ -225,15 +211,15 @@
         inline              LayerVector() { }
                             LayerVector(const LayerVector&);
         inline size_t       size() const { return layers.size(); }
-        inline LayerBase*const* array() const { return layers.array(); }
-        ssize_t             add(LayerBase*, Vector<LayerBase*>::compar_t);
-        ssize_t             remove(LayerBase*);
-        ssize_t             reorder(LayerBase*, Vector<LayerBase*>::compar_t);
-        ssize_t             indexOf(LayerBase* key, size_t guess=0) const;
-        inline LayerBase*   operator [] (size_t i) const { return layers[i]; }
+        inline sp<LayerBase> const* array() const { return layers.array(); }
+        ssize_t             add(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
+        ssize_t             remove(const sp<LayerBase>&);
+        ssize_t             reorder(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
+        ssize_t             indexOf(const sp<LayerBase>& key, size_t guess=0) const;
+        inline sp<LayerBase> operator [] (size_t i) const { return layers[i]; }
     private:
-        KeyedVector<LayerBase*, size_t> lookup;
-        Vector<LayerBase*>              layers;
+        KeyedVector< sp<LayerBase> , size_t> lookup;
+        Vector< sp<LayerBase> >              layers;
     };
 
     struct State {
@@ -247,25 +233,6 @@
         uint8_t         freezeDisplay;
     };
 
-    class DelayedTransaction : public Thread
-    {
-        friend class SurfaceFlinger;
-        sp<SurfaceFlinger>  mFlinger;
-        nsecs_t             mDelay;
-    public:
-        DelayedTransaction(const sp<SurfaceFlinger>& flinger, nsecs_t delay)
-            : Thread(false), mFlinger(flinger), mDelay(delay) {
-        }
-        virtual bool threadLoop() {
-            usleep(mDelay / 1000);
-            if (android_atomic_and(~1,
-                    &mFlinger->mDeplayedTransactionPending) == 1) {
-                mFlinger->signalEvent();
-            }
-            return false;
-        }
-    };
-
     virtual bool        threadLoop();
     virtual status_t    readyToRun();
     virtual void        onFirstRef();
@@ -279,6 +246,9 @@
 
             void        handleConsoleEvents();
             void        handleTransaction(uint32_t transactionFlags);
+            void        handleTransactionLocked(
+                            uint32_t transactionFlags, 
+                            Vector< sp<LayerBase> >& ditchedLayers);
 
             void        computeVisibleRegions(
                             LayerVector& currentLayers,
@@ -289,7 +259,6 @@
             bool        lockPageFlip(const LayerVector& currentLayers);
             void        unlockPageFlip(const LayerVector& currentLayers);
             void        handleRepaint();
-            void        handleDebugCpu();
             void        scheduleBroadcast(Client* client);
             void        executeScheduledBroadcasts();
             void        postFramebuffer();
@@ -298,10 +267,10 @@
 
 
             void        destroyConnection(ClientID cid);
-            LayerBaseClient* getLayerUser_l(SurfaceID index) const;
-            status_t    addLayer_l(LayerBase* layer);
-            status_t    removeLayer_l(LayerBase* layer);
-            void        destroy_all_removed_layers_l();
+            sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const;
+            status_t    addLayer_l(const sp<LayerBase>& layer);
+            status_t    removeLayer_l(const sp<LayerBase>& layer);
+            status_t    purgatorizeLayer_l(const sp<LayerBase>& layer);
             void        free_resources_l();
 
             uint32_t    getTransactionFlags(uint32_t flags);
@@ -323,6 +292,11 @@
             void        debugShowFPS() const;
             void        drawWormhole() const;
            
+
+    mutable     MessageQueue    mEventQueue;
+    
+                
+                
                 // access must be protected by mStateLock
     mutable     Mutex                   mStateLock;
                 State                   mCurrentState;
@@ -330,21 +304,21 @@
     volatile    int32_t                 mTransactionFlags;
     volatile    int32_t                 mTransactionCount;
                 Condition               mTransactionCV;
+                SortedVector< sp<LayerBase> > mLayerPurgatory;
 
+                
                 // protected by mStateLock (but we could use another lock)
                 Tokenizer                               mTokens;
                 DefaultKeyedVector<ClientID, Client*>   mClientsMap;
-                DefaultKeyedVector<SurfaceID, LayerBaseClient*>   mLayerMap;
+                DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> >   mLayerMap;
                 GraphicPlane                            mGraphicPlanes[1];
-                SortedVector<LayerBase*>                mRemovedLayers;
+                bool                                    mLayersRemoved;
                 Vector<Client*>                         mDisconnectedClients;
 
                 // constant members (no synchronization needed for access)
                 sp<MemoryDealer>            mServerHeap;
                 sp<IMemory>                 mServerCblkMemory;
                 surface_flinger_cblk_t*     mServerCblk;
-                sp<SurfaceHeapManager>      mSurfaceHeapManager;
-                sp<GPUHardwareInterface>    mGPU;
                 GLuint                      mWormholeTexName;
                 nsecs_t                     mBootTime;
                 
@@ -360,23 +334,13 @@
                 bool                        mFreezeDisplay;
                 int32_t                     mFreezeCount;
                 nsecs_t                     mFreezeDisplayTime;
-                friend class OrientationAnimation;
-                OrientationAnimation*       mOrientationAnimation;
-
-                // access protected by mDebugLock
-    mutable     Mutex                       mDebugLock;
-                sp<CPUGauge>                mCpuGauge;
 
                 // don't use a lock for these, we don't care
                 int                         mDebugRegion;
-                int                         mDebugCpu;
-                int                         mDebugFps;
                 int                         mDebugBackground;
 
                 // these are thread safe
     mutable     Barrier                     mReadyToRunBarrier;
-    mutable     SurfaceFlingerSynchro       mSyncObject;
-    volatile    int32_t                     mDeplayedTransactionPending;
 
                 // atomic variables
                 enum {
diff --git a/libs/surfaceflinger/Tokenizer.cpp b/libs/surfaceflinger/Tokenizer.cpp
index ef51d6a..be3a239 100644
--- a/libs/surfaceflinger/Tokenizer.cpp
+++ b/libs/surfaceflinger/Tokenizer.cpp
@@ -162,9 +162,10 @@
 {
     const run_t* ranges = mRanges.array();
     const size_t c = mRanges.size();
-    printf("Tokenizer (%p, size = %lu)\n", this, c);
+    printf("Tokenizer (%p, size = %d)\n", this, int(c));
     for (size_t i=0 ; i<c ; i++) {
-        printf("%lu: (%u, %u)\n", i, ranges[i].first, ranges[i].length);
+        printf("%u: (%u, %u)\n", i,
+                uint32_t(ranges[i].first), uint32_t(ranges[i].length));
     }
 }
 
diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp
index e8b0f45..1501536 100644
--- a/libs/surfaceflinger/Transform.cpp
+++ b/libs/surfaceflinger/Transform.cpp
@@ -177,10 +177,10 @@
     Region out;
     if (UNLIKELY(transformed())) {
         if (LIKELY(preserveRects())) {
-            Rect r;
-            Region::iterator iterator(reg);
-            while (iterator.iterate(&r)) {
-                out.orSelf(transform(r));
+            Region::const_iterator it = reg.begin();
+            Region::const_iterator const end = reg.end();
+            while (it != end) {
+                out.orSelf(transform(*it++));
             }
         } else {
             out.set(transform(reg.bounds()));
diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp
similarity index 66%
rename from libs/surfaceflinger/LayerOrientationAnim.cpp
rename to libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp
index 3e4035e..41c42d1 100644
--- a/libs/surfaceflinger/LayerOrientationAnim.cpp
+++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp
@@ -24,10 +24,6 @@
 #include <utils/Log.h>
 #include <utils/StopWatch.h>
 
-#include <core/SkBitmap.h>
-
-#include <ui/EGLDisplaySurface.h>
-
 #include "BlurFilter.h"
 #include "LayerBase.h"
 #include "LayerOrientationAnim.h"
@@ -57,8 +53,8 @@
 LayerOrientationAnim::LayerOrientationAnim(
         SurfaceFlinger* flinger, DisplayID display, 
         OrientationAnimation* anim, 
-        const LayerBitmap& bitmapIn,
-        const LayerBitmap& bitmapOut)
+        const sp<Buffer>& bitmapIn,
+        const sp<Buffer>& bitmapOut)
     : LayerOrientationAnimBase(flinger, display), mAnim(anim), 
       mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), 
       mTextureName(-1), mTextureNameIn(-1)
@@ -77,10 +73,10 @@
 LayerOrientationAnim::~LayerOrientationAnim()
 {
     if (mTextureName != -1U) {
-        LayerBase::deletedTextures.add(mTextureName);
+        glDeleteTextures(1, &mTextureName);
     }
     if (mTextureNameIn != -1U) {
-        LayerBase::deletedTextures.add(mTextureNameIn);
+        glDeleteTextures(1, &mTextureNameIn);
     }
 }
 
@@ -108,11 +104,6 @@
     mTop  = tr.ty();
     transparentRegionScreen.clear();
     mTransformed = true;
-    mCanUseCopyBit = false;
-    copybit_device_t* copybit = mFlinger->getBlitEngine();
-    if (copybit) { 
-        mCanUseCopyBit = true;
-    }
 }
 
 void LayerOrientationAnim::onOrientationCompleted()
@@ -135,7 +126,7 @@
             
             // make a copy of what's on screen
             copybit_image_t image;
-            mBitmapOut.getBitmapSurface(&image);
+            mBitmapOut->getBitmapSurface(&image);
             const DisplayHardware& hw(graphicPlane(0).displayHardware());
             hw.copyBackToImage(image);
 
@@ -194,7 +185,7 @@
     copybit_image_t dst;
     const GraphicPlane& plane(graphicPlane(0));
     const DisplayHardware& hw(plane.displayHardware());
-    hw.getDisplaySurface(&dst);
+    //hw.getDisplaySurface(&dst);
 
     // clear screen
     // TODO: with update on demand, we may be able 
@@ -212,10 +203,10 @@
     }
     
     copybit_image_t src;
-    mBitmapIn.getBitmapSurface(&src);
+    mBitmapIn->getBitmapSurface(&src);
 
     copybit_image_t srcOut;
-    mBitmapOut.getBitmapSurface(&srcOut);
+    mBitmapOut->getBitmapSurface(&srcOut);
 
     const int w = dst.w*scale; 
     const int h = dst.h*scale; 
@@ -225,78 +216,54 @@
     const copybit_rect_t srect = { 0, 0, src.w, src.h };
     const Region reg(Rect( drect.l, drect.t, drect.r, drect.b ));
 
-    int err = NO_ERROR;
-    const int can_use_copybit = canUseCopybit();
-    if (can_use_copybit)  {
-        copybit_device_t* copybit = mFlinger->getBlitEngine();
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-        
-        if (alphaIn > 0) {
-            region_iterator it(reg);
-            copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_ENABLE);
-            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaIn*255));
-            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
-        }
+    GGLSurface t;
+    t.version = sizeof(GGLSurface);
+    t.width  = src.w;
+    t.height = src.h;
+    t.stride = src.w;
+    t.vstride= src.h;
+    t.format = src.format;
+    t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
 
-        if (!err && alphaOut > 0.0f) {
-            region_iterator it(reg);
-            copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE);
-            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaOut*255));
-            err = copybit->stretch(copybit, &dst, &srcOut, &drect, &srect, &it);
-        }
-        LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err));
+    Transform tr;
+    tr.set(scale,0,0,scale);
+    tr.set(xc, yc);
+    
+    // FIXME: we should not access mVertices and mDrawingState like that,
+    // but since we control the animation, we know it's going to work okay.
+    // eventually we'd need a more formal way of doing things like this.
+    LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this));
+    tr.transform(self.mVertices[0], 0, 0);
+    tr.transform(self.mVertices[1], 0, src.h);
+    tr.transform(self.mVertices[2], src.w, src.h);
+    tr.transform(self.mVertices[3], src.w, 0);
+    if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
+        // Too slow to do this in software
+        self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter;
     }
-    if (!can_use_copybit || err) {   
-        GGLSurface t;
-        t.version = sizeof(GGLSurface);
-        t.width  = src.w;
-        t.height = src.h;
-        t.stride = src.w;
-        t.vstride= src.h;
-        t.format = src.format;
+
+    if (alphaIn > 0.0f) {
         t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
-
-        Transform tr;
-        tr.set(scale,0,0,scale);
-        tr.set(xc, yc);
-        
-        // FIXME: we should not access mVertices and mDrawingState like that,
-        // but since we control the animation, we know it's going to work okay.
-        // eventually we'd need a more formal way of doing things like this.
-        LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this));
-        tr.transform(self.mVertices[0], 0, 0);
-        tr.transform(self.mVertices[1], 0, src.h);
-        tr.transform(self.mVertices[2], src.w, src.h);
-        tr.transform(self.mVertices[3], src.w, 0);
-        if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
-            // Too slow to do this in software
-            self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter;
+        if (UNLIKELY(mTextureNameIn == -1LU)) {
+            mTextureNameIn = createTexture();
+            GLuint w=0, h=0;
+            const Region dirty(Rect(t.width, t.height));
+            loadTexture(dirty, mTextureNameIn, t, w, h);
         }
+        self.mDrawingState.alpha = int(alphaIn*255);
+        drawWithOpenGL(reg, mTextureNameIn, t);
+    }
 
-        if (alphaIn > 0.0f) {
-            t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
-            if (UNLIKELY(mTextureNameIn == -1LU)) {
-                mTextureNameIn = createTexture();
-                GLuint w=0, h=0;
-                const Region dirty(Rect(t.width, t.height));
-                loadTexture(dirty, mTextureNameIn, t, w, h);
-            }
-            self.mDrawingState.alpha = int(alphaIn*255);
-            drawWithOpenGL(reg, mTextureNameIn, t);
+    if (alphaOut > 0.0f) {
+        t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset);
+        if (UNLIKELY(mTextureName == -1LU)) {
+            mTextureName = createTexture();
+            GLuint w=0, h=0;
+            const Region dirty(Rect(t.width, t.height));
+            loadTexture(dirty, mTextureName, t, w, h);
         }
-
-        if (alphaOut > 0.0f) {
-            t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset);
-            if (UNLIKELY(mTextureName == -1LU)) {
-                mTextureName = createTexture();
-                GLuint w=0, h=0;
-                const Region dirty(Rect(t.width, t.height));
-                loadTexture(dirty, mTextureName, t, w, h);
-            }
-            self.mDrawingState.alpha = int(alphaOut*255);
-            drawWithOpenGL(reg, mTextureName, t);
-        }
+        self.mDrawingState.alpha = int(alphaOut*255);
+        drawWithOpenGL(reg, mTextureName, t);
     }
 }
 
diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h
similarity index 95%
rename from libs/surfaceflinger/LayerOrientationAnim.h
rename to libs/surfaceflinger/purgatory/LayerOrientationAnim.h
index e86156d..a1a2654 100644
--- a/libs/surfaceflinger/LayerOrientationAnim.h
+++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h
@@ -52,8 +52,8 @@
     
                 LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display,
                         OrientationAnimation* anim, 
-                        const LayerBitmap& bitmapIn,
-                        const LayerBitmap& bitmapOut);
+                        const sp<Buffer>& bitmapIn,
+                        const sp<Buffer>& bitmapOut);
         virtual ~LayerOrientationAnim();
 
             void onOrientationCompleted();
@@ -90,8 +90,8 @@
     };
     
     OrientationAnimation* mAnim;
-    LayerBitmap mBitmapIn;
-    LayerBitmap mBitmapOut;
+    sp<Buffer> mBitmapIn;
+    sp<Buffer> mBitmapOut;
     nsecs_t mStartTime;
     nsecs_t mFinishTime;
     bool mOrientationCompleted;
diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp
similarity index 94%
rename from libs/surfaceflinger/LayerOrientationAnimRotate.cpp
rename to libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp
index 89ffb19..dc6b632 100644
--- a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp
+++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp
@@ -23,10 +23,6 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
-#include <core/SkBitmap.h>
-
-#include <ui/EGLDisplaySurface.h>
-
 #include "LayerBase.h"
 #include "LayerOrientationAnim.h"
 #include "LayerOrientationAnimRotate.h"
@@ -51,10 +47,10 @@
 LayerOrientationAnimRotate::LayerOrientationAnimRotate(
         SurfaceFlinger* flinger, DisplayID display, 
         OrientationAnimation* anim, 
-        const LayerBitmap& bitmap,
-        const LayerBitmap& bitmapIn)
+        const sp<Buffer>& bitmapIn,
+        const sp<Buffer>& bitmapOut)
     : LayerOrientationAnimBase(flinger, display), mAnim(anim), 
-      mBitmap(bitmap), mBitmapIn(bitmapIn), 
+      mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), 
       mTextureName(-1), mTextureNameIn(-1)
 {
     mStartTime = systemTime();
@@ -72,10 +68,10 @@
 LayerOrientationAnimRotate::~LayerOrientationAnimRotate()
 {
     if (mTextureName != -1U) {
-        LayerBase::deletedTextures.add(mTextureName);
+        glDeleteTextures(1, &mTextureName);
     }
     if (mTextureNameIn != -1U) {
-        LayerBase::deletedTextures.add(mTextureNameIn);
+        glDeleteTextures(1, &mTextureNameIn);
     }
 }
 
@@ -103,7 +99,6 @@
     mTop  = tr.ty();
     transparentRegionScreen.clear();
     mTransformed = true;
-    mCanUseCopyBit = false;
 }
 
 void LayerOrientationAnimRotate::onOrientationCompleted()
@@ -126,7 +121,7 @@
         if (mFirstRedraw) {
             // make a copy of what's on screen
             copybit_image_t image;
-            mBitmapIn.getBitmapSurface(&image);
+            mBitmapIn->getBitmapSurface(&image);
             const DisplayHardware& hw(graphicPlane(0).displayHardware());
             hw.copyBackToImage(image);
             
@@ -185,7 +180,7 @@
     copybit_image_t dst;
     const GraphicPlane& plane(graphicPlane(0));
     const DisplayHardware& hw(plane.displayHardware());
-    hw.getDisplaySurface(&dst);
+    //hw.getDisplaySurface(&dst);
 
     // clear screen
     // TODO: with update on demand, we may be able 
@@ -200,7 +195,7 @@
     const int h = dst.h; 
 
     copybit_image_t src;
-    mBitmap.getBitmapSurface(&src);
+    mBitmapIn->getBitmapSurface(&src);
     const copybit_rect_t srect = { 0, 0, src.w, src.h };
 
 
@@ -255,7 +250,7 @@
         tr.transform(self.mVertices[3], src.w, 0);
 
         copybit_image_t src;
-        mBitmapIn.getBitmapSurface(&src);
+        mBitmapIn->getBitmapSurface(&src);
         t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
         if (UNLIKELY(mTextureNameIn == -1LU)) {
             mTextureNameIn = createTexture();
diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.h b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h
similarity index 93%
rename from libs/surfaceflinger/LayerOrientationAnimRotate.h
rename to libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h
index 3296f45..a88eec0 100644
--- a/libs/surfaceflinger/LayerOrientationAnimRotate.h
+++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h
@@ -40,8 +40,8 @@
     
     LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display,
                         OrientationAnimation* anim, 
-                        const LayerBitmap& zoomOut,
-                        const LayerBitmap& zoomIn);
+                        const sp<Buffer>& bitmapIn,
+                        const sp<Buffer>& bitmapOut);
         virtual ~LayerOrientationAnimRotate();
 
             void onOrientationCompleted();
@@ -55,8 +55,8 @@
     void drawScaled(float angle, float scale, float alpha) const;
     
     OrientationAnimation* mAnim;
-    LayerBitmap mBitmap;
-    LayerBitmap mBitmapIn;
+    sp<Buffer> mBitmapIn;
+    sp<Buffer> mBitmapOut;
     nsecs_t mStartTime;
     nsecs_t mFinishTime;
     bool mOrientationCompleted;
diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/purgatory/OrientationAnimation.cpp
similarity index 85%
rename from libs/surfaceflinger/OrientationAnimation.cpp
rename to libs/surfaceflinger/purgatory/OrientationAnimation.cpp
index 70eec8d..a6c9c28 100644
--- a/libs/surfaceflinger/OrientationAnimation.cpp
+++ b/libs/surfaceflinger/purgatory/OrientationAnimation.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdint.h>
 #include <sys/types.h>
 #include <limits.h>
@@ -24,7 +22,6 @@
 #include "LayerOrientationAnimRotate.h"
 #include "OrientationAnimation.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 
 #include "DisplayHardware/DisplayHardware.h"
 
@@ -35,9 +32,6 @@
 OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger)
     : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE)
 {
-    // allocate a memory-dealer for this the first time
-    mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap(
-            ISurfaceComposer::eHardware);
 }
 
 OrientationAnimation::~OrientationAnimation()
@@ -98,19 +92,14 @@
     const uint32_t w = hw.getWidth();
     const uint32_t h = hw.getHeight();
 
-    LayerBitmap bitmap;
-    bitmap.init(mTemporaryDealer);
-    bitmap.setBits(w, h, 1, hw.getFormat());
-
-    LayerBitmap bitmapIn;
-    bitmapIn.init(mTemporaryDealer);
-    bitmapIn.setBits(w, h, 1, hw.getFormat());
+    sp<Buffer> bitmap = new Buffer(w, h, hw.getFormat());
+    sp<Buffer> bitmapIn = new Buffer(w, h, hw.getFormat());
 
     copybit_image_t front;
-    bitmap.getBitmapSurface(&front);
-    hw.copyFrontToImage(front);
+    bitmap->getBitmapSurface(&front);
+    hw.copyFrontToImage(front); // FIXME: we need an extension to do this
 
-    LayerOrientationAnimBase* l;
+    sp<LayerOrientationAnimBase> l;
     
     if (mType & 0x80) {
         l = new LayerOrientationAnimRotate(
@@ -152,7 +141,7 @@
 {
     mState = DONE;
     mFlinger->removeLayer(mLayerOrientationAnim);
-    mLayerOrientationAnim = NULL;
+    mLayerOrientationAnim.clear();
     return true;
 }
 
diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/purgatory/OrientationAnimation.h
similarity index 95%
rename from libs/surfaceflinger/OrientationAnimation.h
rename to libs/surfaceflinger/purgatory/OrientationAnimation.h
index cafa38d..8ba6621 100644
--- a/libs/surfaceflinger/OrientationAnimation.h
+++ b/libs/surfaceflinger/purgatory/OrientationAnimation.h
@@ -72,8 +72,7 @@
     bool finished();
 
     sp<SurfaceFlinger> mFlinger;
-    sp<MemoryDealer> mTemporaryDealer;
-    LayerOrientationAnimBase* mLayerOrientationAnim;
+    sp< LayerOrientationAnimBase > mLayerOrientationAnim;
     int mState;
     uint32_t mType;
 };
diff --git a/libs/surfaceflinger/purgatory/VRamHeap.cpp b/libs/surfaceflinger/purgatory/VRamHeap.cpp
new file mode 100644
index 0000000..f3ed790
--- /dev/null
+++ b/libs/surfaceflinger/purgatory/VRamHeap.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include <utils/MemoryDealer.h>
+#include <utils/MemoryBase.h>
+#include <utils/MemoryHeapPmem.h>
+#include <utils/MemoryHeapBase.h>
+
+#include "GPUHardware/GPUHardware.h"
+#include "SurfaceFlinger.h"
+#include "VRamHeap.h"
+
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#endif
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+/*
+ * Amount of memory we reserve for surface, per client in PMEM
+ * (PMEM is used for 2D acceleration)
+ * 8 MB of address space per client should be enough.
+ */
+static const int PMEM_SIZE = int(8 * 1024 * 1024);
+
+int SurfaceHeapManager::global_pmem_heap = 0;
+
+// ---------------------------------------------------------------------------
+
+SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, 
+        size_t clientHeapSize)
+    : mFlinger(flinger), mClientHeapSize(clientHeapSize)
+{
+    SurfaceHeapManager::global_pmem_heap = 1;
+}
+
+SurfaceHeapManager::~SurfaceHeapManager()
+{
+}
+
+void SurfaceHeapManager::onFirstRef()
+{
+    if (global_pmem_heap) {
+        const char* device = "/dev/pmem";
+        mPMemHeap = new PMemHeap(device, PMEM_SIZE);
+        if (mPMemHeap->base() == MAP_FAILED) {
+            mPMemHeap.clear();
+            global_pmem_heap = 0;
+        }
+    }
+}
+
+sp<MemoryDealer> SurfaceHeapManager::createHeap(
+        uint32_t flags,
+        pid_t client_pid,
+        const sp<MemoryDealer>& defaultAllocator)
+{
+    sp<MemoryDealer> dealer; 
+
+    if (flags & ISurfaceComposer::eGPU) {
+        // don't grant GPU memory if GPU is disabled
+        char value[PROPERTY_VALUE_MAX];
+        property_get("debug.egl.hw", value, "1");
+        if (atoi(value) == 0) {
+            flags &= ~ISurfaceComposer::eGPU;
+        }
+    }
+
+    if (flags & ISurfaceComposer::eGPU) {
+        // FIXME: this is msm7201A specific, where gpu surfaces may not be secure
+        if (!(flags & ISurfaceComposer::eSecure)) {
+            // if GPU doesn't work, we try eHardware
+            flags |= ISurfaceComposer::eHardware;
+            // asked for GPU memory, try that first
+            dealer = mFlinger->getGPU()->request(client_pid);
+        }
+    }
+
+    if (dealer == NULL) {
+        if (defaultAllocator != NULL)
+            // if a default allocator is given, use that
+            dealer = defaultAllocator;
+    }
+    
+    if (dealer == NULL) {
+        // always try h/w accelerated memory first
+        if (global_pmem_heap) {
+            const sp<PMemHeap>& heap(mPMemHeap);
+            if (dealer == NULL && heap != NULL) {
+                dealer = new MemoryDealer( 
+                        heap->createClientHeap(),
+                        heap->getAllocator());
+            }
+        }
+    }
+
+    if (dealer == NULL) {
+        // return the ashmem allocator (software rendering)
+        dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap");
+    }
+    return dealer;
+}
+
+sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const 
+{
+    Mutex::Autolock _l(mLock);
+    sp<SimpleBestFitAllocator> allocator;
+
+    // this is only used for debugging
+    switch (type) {
+        case NATIVE_MEMORY_TYPE_PMEM:
+            if (mPMemHeap != 0) {
+                allocator = mPMemHeap->getAllocator();
+            }
+            break;
+    }
+    return allocator;
+}
+
+// ---------------------------------------------------------------------------
+
+PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved)
+    : MemoryHeapBase(device, size)
+{
+    //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
+    if (base() != MAP_FAILED) {
+        //LOGD("%s, %u bytes", device, virtualSize());
+        if (reserved == 0)
+            reserved = virtualSize();
+        mAllocator = new SimpleBestFitAllocator(reserved);
+    }
+}
+
+PMemHeap::~PMemHeap() {
+    //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
+}
+
+sp<MemoryHeapPmem> PMemHeap::createClientHeap() {
+    sp<MemoryHeapBase> parentHeap(this);
+    return new MemoryHeapPmem(parentHeap);
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/surfaceflinger/purgatory/VRamHeap.h b/libs/surfaceflinger/purgatory/VRamHeap.h
new file mode 100644
index 0000000..9140167
--- /dev/null
+++ b/libs/surfaceflinger/purgatory/VRamHeap.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VRAM_HEAP_H
+#define ANDROID_VRAM_HEAP_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/MemoryDealer.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class PMemHeap;
+class MemoryHeapPmem;
+class SurfaceFlinger; 
+
+// ---------------------------------------------------------------------------
+
+class SurfaceHeapManager  : public RefBase
+{
+public:
+    SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize);
+    virtual ~SurfaceHeapManager();
+    virtual void onFirstRef();
+    /* use ISurfaceComposer flags eGPU|eHArdware|eSecure */
+    sp<MemoryDealer> createHeap(uint32_t flags=0, pid_t client_pid = 0,
+            const sp<MemoryDealer>& defaultAllocator = 0);
+    
+    // used for debugging only...
+    sp<SimpleBestFitAllocator> getAllocator(int type) const;
+
+private:
+    sp<PMemHeap> getHeap(int type) const;
+
+    sp<SurfaceFlinger> mFlinger;
+    mutable Mutex   mLock;
+    size_t          mClientHeapSize;
+    sp<PMemHeap>    mPMemHeap;
+    static int global_pmem_heap;
+};
+
+// ---------------------------------------------------------------------------
+
+class PMemHeap : public MemoryHeapBase
+{
+public:
+                PMemHeap(const char* const vram,
+                        size_t size=0, size_t reserved=0);
+    virtual     ~PMemHeap();
+    
+    virtual const sp<SimpleBestFitAllocator>& getAllocator() const {
+        return mAllocator; 
+    }
+    virtual sp<MemoryHeapPmem> createClientHeap();
+    
+private:
+    sp<SimpleBestFitAllocator>  mAllocator;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_VRAM_HEAP_H
diff --git a/libs/surfaceflinger/tests/resize/Android.mk b/libs/surfaceflinger/tests/resize/Android.mk
new file mode 100644
index 0000000..ef1532f
--- /dev/null
+++ b/libs/surfaceflinger/tests/resize/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	resize.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+    libui
+
+LOCAL_MODULE:= test-resize
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/libs/surfaceflinger/tests/resize/resize.cpp b/libs/surfaceflinger/tests/resize/resize.cpp
new file mode 100644
index 0000000..21c6ab6
--- /dev/null
+++ b/libs/surfaceflinger/tests/resize/resize.cpp
@@ -0,0 +1,60 @@
+#include <cutils/memory.h>
+
+#include <utils/IPCThreadState.h>
+#include <utils/ProcessState.h>
+#include <utils/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <ui/Surface.h>
+#include <ui/ISurface.h>
+#include <ui/Overlay.h>
+#include <ui/SurfaceComposerClient.h>
+
+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)
+{
+    // set up the thread-pool
+    sp<ProcessState> proc(ProcessState::self());
+    ProcessState::self()->startThreadPool();
+
+    // create a client to surfaceflinger
+    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
+    
+    // create pushbuffer surface
+    sp<Surface> surface = client->createSurface(getpid(), 0, 160, 240, 
+            PIXEL_FORMAT_RGB_565);
+
+
+    client->openTransaction();
+    surface->setLayer(100000);
+    client->closeTransaction();
+
+    Surface::SurfaceInfo info;
+    surface->lock(&info);
+    ssize_t bpr = info.s * bytesPerPixel(info.format);
+    android_memset16((uint16_t*)info.bits, 0xF800, bpr*info.h);
+    surface->unlockAndPost();
+
+    surface->lock(&info);
+    android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h);
+    surface->unlockAndPost();
+
+    client->openTransaction();
+    surface->setSize(320, 240);
+    client->closeTransaction();
+
+    
+    IPCThreadState::self()->joinThreadPool();
+    
+    return 0;
+}
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index c6fd070..38ef8b9 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -2,12 +2,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
+	BufferMapper.cpp \
 	Camera.cpp \
 	CameraParameters.cpp \
-	EGLDisplaySurface.cpp \
-	EGLNativeWindowSurface.cpp \
 	EventHub.cpp \
 	EventRecurrence.cpp \
+	FramebufferNativeWindow.cpp \
 	KeyLayoutMap.cpp \
 	KeyCharacterMap.cpp \
 	ICamera.cpp \
@@ -28,7 +28,6 @@
 	Time.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libcorecg \
 	libcutils \
 	libutils \
 	libbinder \
diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp
new file mode 100644
index 0000000..92a9a86
--- /dev/null
+++ b/libs/ui/BufferMapper.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BufferMapper"
+
+#include <stdint.h>
+#include <errno.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <ui/BufferMapper.h>
+#include <ui/Rect.h>
+
+#include <hardware/gralloc.h>
+
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE( BufferMapper )
+
+BufferMapper::BufferMapper()
+    : mAllocMod(0)
+{
+    hw_module_t const* module;
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+    if (err == 0) {
+        mAllocMod = (gralloc_module_t const *)module;
+    }
+}
+
+status_t BufferMapper::registerBuffer(buffer_handle_t handle)
+{
+    status_t err = mAllocMod->registerBuffer(mAllocMod, handle);
+    LOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
+            handle, err, strerror(-err));
+    return err;
+}
+
+status_t BufferMapper::unregisterBuffer(buffer_handle_t handle)
+{
+    status_t err = mAllocMod->unregisterBuffer(mAllocMod, handle);
+    LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",
+            handle, err, strerror(-err));
+    return err;
+}
+
+status_t BufferMapper::lock(buffer_handle_t handle, 
+        int usage, const Rect& bounds, void** vaddr)
+{
+    status_t err = mAllocMod->lock(mAllocMod, handle, usage,
+            bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr);
+    LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+status_t BufferMapper::unlock(buffer_handle_t handle)
+{
+    status_t err = mAllocMod->unlock(mAllocMod, handle);
+    LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp
deleted file mode 100644
index d06c98b..0000000
--- a/libs/ui/EGLDisplaySurface.cpp
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- **
- ** Copyright 2007 The Android Open Source Project
- **
- ** Licensed under the Apache License Version 2.0(the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- **     http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing software
- ** distributed under the License is distributed on an "AS IS" BASIS
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#define LOG_TAG "EGLDisplaySurface"
-
-#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/log.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-
-#include <hardware/copybit.h>
-
-#include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <ui/EGLDisplaySurface.h>
-
-#if HAVE_ANDROID_OS
-#include <linux/msm_mdp.h>
-#endif
-
-#include <EGL/egl.h>
-
-#include <pixelflinger/format.h>
-
-
-// ----------------------------------------------------------------------------
-
-egl_native_window_t* android_createDisplaySurface()
-{
-    egl_native_window_t* s = new android::EGLDisplaySurface();
-    s->memory_type = NATIVE_MEMORY_TYPE_GPU;
-    return s;
-}
-
-#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
-#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-EGLDisplaySurface::EGLDisplaySurface()
-    : EGLNativeSurface<EGLDisplaySurface>()
-{
-    egl_native_window_t::version = sizeof(egl_native_window_t);
-    egl_native_window_t::ident = 0;
-    egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef;
-    egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef;
-    egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers;
-    egl_native_window_t::connect = 0;
-    egl_native_window_t::disconnect = 0;
-
-    mFb[0].data = 0;
-    mFb[1].data = 0;
-    mBlitEngine = 0;
-    egl_native_window_t::fd = mapFrameBuffer();
-    if (egl_native_window_t::fd >= 0) {
-        
-        hw_module_t const* module;
-        if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
-            copybit_open(module, &mBlitEngine);
-        }
-        
-        const float in2mm = 25.4f;
-        float refreshRate = 1000000000000000LLU / (
-                float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres )
-                * ( mInfo.left_margin  + mInfo.right_margin + mInfo.xres )
-                * mInfo.pixclock);
-
-        const GGLSurface& buffer = mFb[1 - mIndex];
-        egl_native_window_t::width  = buffer.width;
-        egl_native_window_t::height = buffer.height;
-        egl_native_window_t::stride = buffer.stride;
-        egl_native_window_t::format = buffer.format;
-        egl_native_window_t::base   = intptr_t(mFb[0].data);
-        egl_native_window_t::offset =
-            intptr_t(buffer.data) - egl_native_window_t::base;
-        egl_native_window_t::flags  = 0;
-        egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width;
-        egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height;
-        egl_native_window_t::fps  = refreshRate;
-        egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB;
-        // no error, set the magic word
-        egl_native_window_t::magic = 0x600913;
-    }
-    mSwapCount = -1;
-    mPageFlipCount = 0;
-}
-
-EGLDisplaySurface::~EGLDisplaySurface()
-{
-    magic = 0;
-    copybit_close(mBlitEngine);
-    mBlitEngine = 0;
-    close(egl_native_window_t::fd);
-    munmap(mFb[0].data, mSize);
-    if (!(mFlags & PAGE_FLIP))
-        free((void*)mFb[1].data);
-}
-
-void EGLDisplaySurface::hook_incRef(NativeWindowType window) {
-    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
-    that->incStrong(that);
-}
-void EGLDisplaySurface::hook_decRef(NativeWindowType window) {
-    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
-    that->decStrong(that);
-}
-uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) {
-    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
-    return that->swapBuffers();
-}
-
-void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h)
-{
-    mInfo.reserved[0] = 0x54445055; // "UPDT";
-    mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
-    mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
-}
-
-uint32_t EGLDisplaySurface::swapBuffers()
-{
-#define SHOW_FPS 0
-#if SHOW_FPS
-    nsecs_t now = systemTime();
-    if (mSwapCount == -1) {
-        mTime = now;
-        mSwapCount = 0;
-        mSleep = 0;
-    } else {
-        nsecs_t d = now-mTime;
-        if (d >= seconds(1)) {
-            double fps = (mSwapCount * double(seconds(1))) / double(d);
-            LOGD("%f fps, sleep=%d / frame",
-                    fps, (int)ns2us(mSleep / mSwapCount));
-            mSwapCount = 0;
-            mTime = now;
-            mSleep = 0;
-        } else {
-            mSwapCount++;
-        }
-    }
-#endif
-    /* If we can't do the page_flip, just copy the back buffer to the front */
-    if (!(mFlags & PAGE_FLIP)) {
-        memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2);
-        return 0;
-    }
-
-    // do the actual flip
-    mIndex = 1 - mIndex;
-    mInfo.activate = FB_ACTIVATE_VBL;
-    mInfo.yoffset = mIndex ? mInfo.yres : 0;
-    if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) {
-        LOGE("FBIOPUT_VSCREENINFO failed");
-        return 0;
-    }
-
-    /*
-     * this is a monstrous hack: Because the h/w accelerator is not able
-     * to render directly into the framebuffer, we need to copy its
-     * internal framebuffer out to the fb.
-     * oem[0] is used to access the fd of internal fb.
-     * All this is needed only in standalone mode, in SurfaceFlinger mode
-     * we control where the GPU renders.
-     * We do this only if we have copybit, since this hack is needed only
-     * with msm7k.
-     */
-    if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0] && mBlitEngine) {
-        copybit_device_t *copybit = mBlitEngine;
-        copybit_rect_t sdrect = { 0, 0,
-                egl_native_window_t::width, egl_native_window_t::height };
-        copybit_image_t dst = {
-                egl_native_window_t::width,
-                egl_native_window_t::height,
-                egl_native_window_t::format,
-                egl_native_window_t::offset,
-                (void*)egl_native_window_t::base,
-                egl_native_window_t::fd
-        };
-        copybit_image_t src = {
-                egl_native_window_t::width,
-                egl_native_window_t::height,
-                egl_native_window_t::format, // XXX: use proper format
-                egl_native_window_t::offset,
-                (void*)egl_native_window_t::base,  // XXX: use proper base
-                egl_native_window_t::oem[0]
-        };
-        region_iterator it(Region(Rect(
-                egl_native_window_t::width, egl_native_window_t::height)));
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
-        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
-        copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it);
-    }
-
-    // update the address of the buffer to draw to next
-    const GGLSurface& buffer = mFb[1 - mIndex];
-    egl_native_window_t::offset =
-        intptr_t(buffer.data) - egl_native_window_t::base;
-
-#if SHOW_FPS
-    mSleep += systemTime()-now;
-#endif
-
-    mPageFlipCount++;
-
-    // We don't support screen-size changes for now
-    return 0;
-}
-
-int32_t EGLDisplaySurface::getPageFlipCount() const
-{
-    return mPageFlipCount;
-}
-
-void EGLDisplaySurface::copyFrontToBack(const Region& copyback)
-{
-#if HAVE_ANDROID_OS
-    if (mBlitEngine) {
-        copybit_image_t dst = {
-                w:      egl_native_window_t::stride,
-                h:      egl_native_window_t::height,
-                format: egl_native_window_t::format,
-                offset: mFb[1-mIndex].data - mFb[0].data,
-                base:   (void*)egl_native_window_t::base,
-                fd:     egl_native_window_t::fd
-        };
-        copybit_image_t src = {
-                w:      egl_native_window_t::stride,
-                h:      egl_native_window_t::height,
-                format: egl_native_window_t::format,
-                offset: mFb[mIndex].data - mFb[0].data,
-                base:   (void*)egl_native_window_t::base,
-                fd:     egl_native_window_t::fd
-        };
-        region_iterator it(copyback);
-        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
-    } else
-#endif
-    {
-        /* no extra copy needed since we copied back to front instead of
-         * flipping */
-        if (!(mFlags & PAGE_FLIP)) {
-            return;
-        }
-
-        Region::iterator iterator(copyback);
-        if (iterator) {
-            Rect r;
-            uint8_t* const screen_src = mFb[  mIndex].data;
-            uint8_t* const screen_dst = mFb[1-mIndex].data;
-            const size_t bpp = bytesPerPixel(egl_native_window_t::format);
-            const size_t bpr = egl_native_window_t::stride * bpp;
-            while (iterator.iterate(&r)) {
-                ssize_t h = r.bottom - r.top;
-                if (h) {
-                    size_t size = (r.right - r.left) * bpp;
-                    size_t o = (r.left + egl_native_window_t::stride * r.top) * bpp;
-                    uint8_t* s = screen_src + o;
-                    uint8_t* d = screen_dst + o;
-                    if (size == bpr) {
-                        size *= h;
-                        h = 1;
-                    }
-                    do {
-                        memcpy(d, s, size);
-                        d += bpr;
-                        s += bpr;
-                    } while (--h > 0);
-                }
-            }
-        }
-    }
-}
-
-void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst)
-{
-#if HAVE_ANDROID_OS
-    if (mBlitEngine) {
-        copybit_image_t src = {
-                w:      egl_native_window_t::stride,
-                h:      egl_native_window_t::height,
-                format: egl_native_window_t::format,
-                offset: mFb[mIndex].data - mFb[0].data,
-                base:   (void*)egl_native_window_t::base,
-                fd:     egl_native_window_t::fd
-        };
-        region_iterator it(Region(Rect(
-                egl_native_window_t::width, egl_native_window_t::height)));
-        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
-    } else
-#endif
-    {
-        uint8_t* const screen_src = mFb[  mIndex].data;
-        const size_t bpp = bytesPerPixel(egl_native_window_t::format);
-        const size_t bpr = egl_native_window_t::stride * bpp;
-        memcpy((char*)dst.base + dst.offset, screen_src,
-                bpr*egl_native_window_t::height);
-    }
-}
-
-void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst)
-{
-#if HAVE_ANDROID_OS
-    if (mBlitEngine) {
-        copybit_image_t src = {
-                w:      egl_native_window_t::stride,
-                h:      egl_native_window_t::height,
-                format: egl_native_window_t::format,
-                offset: mFb[1-mIndex].data - mFb[0].data,
-                base:   (void*)egl_native_window_t::base,
-                fd:     egl_native_window_t::fd
-        };
-        region_iterator it(Region(Rect(
-                egl_native_window_t::width, egl_native_window_t::height)));
-        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
-    } else
-#endif
-    {
-        uint8_t* const screen_src = mFb[1-mIndex].data;
-        const size_t bpp = bytesPerPixel(egl_native_window_t::format);
-        const size_t bpr = egl_native_window_t::stride * bpp;
-        memcpy((char*)dst.base + dst.offset, screen_src,
-                bpr*egl_native_window_t::height);
-    }
-}
-
-
-status_t EGLDisplaySurface::mapFrameBuffer()
-{
-    char const * const device_template[] = {
-            "/dev/graphics/fb%u",
-            "/dev/fb%u",
-            0 };
-    int fd = -1;
-    int i=0;
-    char name[64];
-    while ((fd==-1) && device_template[i]) {
-        snprintf(name, 64, device_template[i], 0);
-        fd = open(name, O_RDWR, 0);
-        i++;
-    }
-    if (fd < 0)
-        return -errno;
-
-    struct fb_fix_screeninfo finfo;
-    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
-        return -errno;
-
-    struct fb_var_screeninfo info;
-    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
-        return -errno;
-
-    info.reserved[0] = 0;
-    info.reserved[1] = 0;
-    info.reserved[2] = 0;
-    info.xoffset = 0;
-    info.yoffset = 0;
-    info.yres_virtual = info.yres * 2;
-    info.bits_per_pixel = 16;
-    /* Explicitly request 5/6/5 */
-    info.red.offset = 11;
-    info.red.length = 5;
-    info.green.offset = 5;
-    info.green.length = 6;
-    info.blue.offset = 0;
-    info.blue.length = 5;
-    info.transp.offset = 0;
-    info.transp.length = 0;
-    info.activate = FB_ACTIVATE_NOW;
-
-    uint32_t flags = PAGE_FLIP;
-    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
-        info.yres_virtual = info.yres;
-        flags &= ~PAGE_FLIP;
-        LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
-    }
-
-    if (info.yres_virtual < info.yres * 2) {
-        info.yres_virtual = info.yres;
-        flags &= ~PAGE_FLIP;
-        LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
-                info.yres_virtual, info.yres*2);
-    }
-
-    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
-        return -errno;
-
-    int refreshRate = 1000000000000000LLU /
-    (
-            uint64_t( info.upper_margin + info.lower_margin + info.yres )
-            * ( info.left_margin  + info.right_margin + info.xres )
-            * info.pixclock
-    );
-
-    if (refreshRate == 0) {
-        // bleagh, bad info from the driver
-        refreshRate = 60*1000;  // 60 Hz
-    }
-    if (int(info.width) <= 0 || int(info.height) <= 0) {
-        // the driver doesn't return that information
-        // default to 160 dpi
-        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
-        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
-    }
-
-    float xdpi = (info.xres * 25.4f) / info.width;
-    float ydpi = (info.yres * 25.4f) / info.height;
-    float fps  = refreshRate / 1000.0f;
-
-    LOGI(   "using (fd=%d)\n"
-            "id           = %s\n"
-            "xres         = %d px\n"
-            "yres         = %d px\n"
-            "xres_virtual = %d px\n"
-            "yres_virtual = %d px\n"
-            "bpp          = %d\n"
-            "r            = %2u:%u\n"
-            "g            = %2u:%u\n"
-            "b            = %2u:%u\n",
-            fd,
-            finfo.id,
-            info.xres,
-            info.yres,
-            info.xres_virtual,
-            info.yres_virtual,
-            info.bits_per_pixel,
-            info.red.offset, info.red.length,
-            info.green.offset, info.green.length,
-            info.blue.offset, info.blue.length
-    );
-
-    LOGI(   "width        = %d mm (%f dpi)\n"
-            "height       = %d mm (%f dpi)\n"
-            "refresh rate = %.2f Hz\n",
-            info.width,  xdpi,
-            info.height, ydpi,
-            fps
-    );
-
-
-    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
-        return -errno;
-
-    if (finfo.smem_len <= 0)
-        return -errno;
-
-    /*
-     * Open and map the display.
-     */
-
-    void* buffer  = (uint16_t*) mmap(
-            0, finfo.smem_len,
-            PROT_READ | PROT_WRITE,
-            MAP_SHARED,
-            fd, 0);
-
-    if (buffer == MAP_FAILED)
-        return -errno;
-
-    // at least for now, always clear the fb
-    memset(buffer, 0, finfo.smem_len);
-
-    uint8_t* offscreen[2];
-    offscreen[0] = (uint8_t*)buffer;
-    if (flags & PAGE_FLIP) {
-        offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres;
-    } else {
-        offscreen[1] = (uint8_t*)malloc(finfo.smem_len);
-        if (offscreen[1] == 0) {
-            munmap(buffer, finfo.smem_len);
-            return NO_MEMORY;
-        }
-    }
-
-    mFlags = flags;
-    mInfo = info;
-    mFinfo = finfo;
-    mSize = finfo.smem_len;
-    mIndex = 0;
-    for (int i=0 ; i<2 ; i++) {
-        mFb[i].version = sizeof(GGLSurface);
-        mFb[i].width   = info.xres;
-        mFb[i].height  = info.yres;
-        mFb[i].stride  = finfo.line_length / (info.bits_per_pixel >> 3);
-        mFb[i].data    = (GGLubyte*)(offscreen[i]);
-        mFb[i].format  = GGL_PIXEL_FORMAT_RGB_565;
-    }
-    return fd;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp
deleted file mode 100644
index f1071cf..0000000
--- a/libs/ui/EGLNativeWindowSurface.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/* 
-**
-** Copyright 2007 The Android Open Source Project
-**
-** Licensed under the Apache License Version 2.0(the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing software 
-** distributed under the License is distributed on an "AS IS" BASIS 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#define LOG_TAG "EGLNativeWindowSurface"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <cutils/log.h>
-#include <cutils/atomic.h>
-
-#include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
-#include <ui/Rect.h>
-
-#include <EGL/egl.h>
-
-#include <pixelflinger/format.h>
-
-#include <ui/EGLNativeWindowSurface.h>
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface)
-    : EGLNativeSurface<EGLNativeWindowSurface>(),
-    mSurface(surface), mConnected(false)
-{
-    egl_native_window_t::magic = 0x600913;
-    egl_native_window_t::version = sizeof(egl_native_window_t);
-    egl_native_window_t::ident = 0;
-    egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef;
-    egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef;
-    egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers;
-    egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect;
-    egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect;
-    
-    DisplayInfo dinfo;
-    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
-    egl_native_window_t::xdpi = dinfo.xdpi;
-    egl_native_window_t::ydpi = dinfo.ydpi;
-    egl_native_window_t::fps  = dinfo.fps;
-    egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER;
-}
-
-EGLNativeWindowSurface::~EGLNativeWindowSurface()
-{
-    disconnect();
-    mSurface.clear();
-    magic = 0;
-}
-
-void EGLNativeWindowSurface::hook_incRef(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->incStrong(that);
-}
-
-void EGLNativeWindowSurface::hook_decRef(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->decStrong(that);
-}
-
-void EGLNativeWindowSurface::hook_connect(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->connect();
-}
-
-void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->disconnect();
-}
-
-uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    return that->swapBuffers();
-}
-
-void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h)
-{
-    mSurface->setSwapRectangle(Rect(l, t, l+w, t+h));
-}
-
-uint32_t EGLNativeWindowSurface::swapBuffers()
-{
-    const int w = egl_native_window_t::width;
-    const int h = egl_native_window_t::height;
-    const sp<Surface>& surface(mSurface);
-    Surface::SurfaceInfo info;
-    surface->unlockAndPost();
-    surface->lock(&info);
-    // update the address of the buffer to draw to next
-    egl_native_window_t::base   = intptr_t(info.base);
-    egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
-    
-    // update size if it changed
-    if (w != int(info.w) || h != int(info.h)) {
-        egl_native_window_t::width  = info.w;
-        egl_native_window_t::height = info.h;
-        egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
-        egl_native_window_t::format = info.format;
-        return EGL_NATIVES_FLAG_SIZE_CHANGED;
-    }
-    return 0;
-}
-
-void EGLNativeWindowSurface::connect()
-{   
-    if (!mConnected) {
-        Surface::SurfaceInfo info;
-        mSurface->lock(&info);
-        mSurface->setSwapRectangle(Rect(info.w, info.h));
-        mConnected = true;
-
-        egl_native_window_t::width  = info.w;
-        egl_native_window_t::height = info.h;
-        egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
-        egl_native_window_t::format = info.format;
-        egl_native_window_t::base   = intptr_t(info.base);
-        egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
-        // FIXME: egl_native_window_t::memory_type used to be set from
-        // mSurface, but we wanted to break this dependency. We set it to
-        // GPU because the software rendered doesn't care, but the h/w
-        // accelerator needs it. Eventually, this value should go away
-        // completely, since memory will be managed by OpenGL.
-        egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU; 
-        egl_native_window_t::fd = 0;
-    }
-}
-
-void EGLNativeWindowSurface::disconnect()
-{
-    if (mConnected) {
-        mSurface->unlock();
-        mConnected = false;
-    }
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
new file mode 100644
index 0000000..8c8fd6b
--- /dev/null
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -0,0 +1,210 @@
+/* 
+**
+** Copyright 2007 The Android Open Source Project
+**
+** Licensed under the Apache License Version 2.0(the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing software 
+** distributed under the License is distributed on an "AS IS" BASIS 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#define LOG_TAG "FramebufferNativeWindow"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <utils/threads.h>
+
+#include <ui/SurfaceComposerClient.h>
+#include <ui/Rect.h>
+#include <ui/FramebufferNativeWindow.h>
+
+#include <EGL/egl.h>
+
+#include <pixelflinger/format.h>
+#include <pixelflinger/pixelflinger.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include <private/ui/android_natives_priv.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class NativeBuffer 
+    : public EGLNativeBase<
+        android_native_buffer_t, 
+        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;
+    }
+private:
+    friend class LightRefBase<NativeBuffer>;    
+    ~NativeBuffer() { }; // this class cannot be overloaded
+};
+
+
+/*
+ * This implements the (main) framebuffer management. This class is used
+ * mostly by SurfaceFlinger, but also by command line GL application.
+ * 
+ * In fact this is an implementation of android_native_window_t on top of
+ * the framebuffer.
+ * 
+ * Currently it is pretty simple, it manages only two buffers (the front and 
+ * back buffer).
+ * 
+ */
+
+FramebufferNativeWindow::FramebufferNativeWindow() 
+    : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
+{
+    hw_module_t const* module;
+    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+        int stride;
+        framebuffer_open(module, &fbDev);
+        gralloc_open(module, &grDev);
+        int err;
+
+        
+        mUpdateOnDemand = (fbDev->setUpdateRect != 0);
+        
+        // initialize the buffer FIFO
+        mNumBuffers = 2;
+        mNumFreeBuffers = 2;
+        mBufferHead = mNumBuffers-1;
+        buffers[0] = new NativeBuffer(
+                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        buffers[1] = new NativeBuffer(
+                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        
+        err = grDev->alloc(grDev,
+                fbDev->width, fbDev->height, fbDev->format, 
+                GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
+
+        LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
+                fbDev->width, fbDev->height, strerror(-err));
+
+        err = grDev->alloc(grDev,
+                fbDev->width, fbDev->height, fbDev->format, 
+                GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
+
+        LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
+                fbDev->width, fbDev->height, strerror(-err));
+    }
+
+    const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; 
+    const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
+    const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi;
+    const_cast<int&>(android_native_window_t::minSwapInterval) = 
+        fbDev->minSwapInterval;
+    const_cast<int&>(android_native_window_t::maxSwapInterval) = 
+        fbDev->maxSwapInterval;
+
+    android_native_window_t::setSwapInterval = setSwapInterval;
+    android_native_window_t::dequeueBuffer = dequeueBuffer;
+    android_native_window_t::lockBuffer = lockBuffer;
+    android_native_window_t::queueBuffer = queueBuffer;
+}
+
+FramebufferNativeWindow::~FramebufferNativeWindow() {
+    grDev->free(grDev, buffers[0]->handle);
+    grDev->free(grDev, buffers[1]->handle);
+    gralloc_close(grDev);
+    framebuffer_close(fbDev);
+}
+
+status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r) 
+{
+    if (!mUpdateOnDemand) {
+        return INVALID_OPERATION;
+    }
+    return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
+}
+
+int FramebufferNativeWindow::setSwapInterval(
+        android_native_window_t* window, int interval) 
+{
+    framebuffer_device_t* fb = getSelf(window)->fbDev;
+    return fb->setSwapInterval(fb, interval);
+}
+
+int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, 
+        android_native_buffer_t** buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
+
+    // wait for a free buffer
+    while (!self->mNumFreeBuffers) {
+        self->mCondition.wait(self->mutex);
+    }
+    // get this buffer
+    self->mNumFreeBuffers--;
+    int index = self->mBufferHead++;
+    if (self->mBufferHead >= self->mNumBuffers)
+        self->mBufferHead = 0;
+
+    *buffer = self->buffers[index].get();
+
+    return 0;
+}
+
+int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+
+    // wait that the buffer we're locking is not front anymore
+    while (self->front == buffer) {
+        self->mCondition.wait(self->mutex);
+    }
+
+    return NO_ERROR;
+}
+
+int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
+    buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
+    int res = fb->post(fb, handle);
+    self->front = static_cast<NativeBuffer*>(buffer);
+    self->mNumFreeBuffers++;
+    self->mCondition.broadcast();
+    return res;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+
+EGLNativeWindowType android_createDisplaySurface(void)
+{
+    return new android::FramebufferNativeWindow();
+}
+
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index 1e60557..9fbae1e 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "ISurface"
+
 #include <stdio.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -23,10 +25,14 @@
 
 #include <ui/ISurface.h>
 #include <ui/Overlay.h>
+#include <ui/Surface.h>
 
+#include <private/ui/SurfaceBuffer.h>
 
 namespace android {
 
+// ----------------------------------------------------------------------
+
 ISurface::BufferHeap::BufferHeap() 
     : w(0), h(0), hor_stride(0), ver_stride(0), format(0),
     transform(0), flags(0) 
@@ -55,6 +61,8 @@
 {     
 }
 
+// ----------------------------------------------------------------------
+
 class BpSurface : public BpInterface<ISurface>
 {
 public:
@@ -63,6 +71,15 @@
     {
     }
 
+    virtual sp<SurfaceBuffer> getBuffer()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        remote()->transact(GET_BUFFER, data, &reply);
+        sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply);
+        return buffer;
+    }
+
     virtual status_t registerBuffers(const BufferHeap& buffers)
     {
         Parcel data, reply;
@@ -116,6 +133,11 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
+        case GET_BUFFER: {
+            CHECK_INTERFACE(ISurface, data, reply);
+            sp<SurfaceBuffer> buffer(getBuffer());
+            return SurfaceBuffer::writeToParcel(reply, buffer.get());
+        }
         case REGISTER_BUFFERS: {
             CHECK_INTERFACE(ISurface, data, reply);
             BufferHeap buffer;
diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp
index 5f558a1..2aa1405 100644
--- a/libs/ui/ISurfaceComposer.cpp
+++ b/libs/ui/ISurfaceComposer.cpp
@@ -114,36 +114,6 @@
         remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
     }
 
-    virtual status_t requestGPU(
-            const sp<IGPUCallback>& callback, gpu_info_t* gpu)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeStrongBinder(callback->asBinder());
-        remote()->transact(BnSurfaceComposer::REQUEST_GPU, data, &reply);
-        gpu->regs = interface_cast<IMemory>(reply.readStrongBinder());
-        gpu->count = reply.readInt32();
-
-        // FIXME: for now, we don't dynamically allocate the regions array
-        size_t maxCount = sizeof(gpu->regions)/sizeof(*gpu->regions);
-        if (gpu->count > maxCount)
-            return BAD_VALUE;
-
-        for (size_t i=0 ; i<gpu->count ; i++) {
-            gpu->regions[i].region = interface_cast<IMemory>(reply.readStrongBinder());
-            gpu->regions[i].reserved = reply.readInt32();
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t revokeGPU()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        remote()->transact(BnSurfaceComposer::REVOKE_GPU, data, &reply);
-        return reply.readInt32();
-    }
-
     virtual void signal() const
     {
         Parcel data, reply;
@@ -196,10 +166,6 @@
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             bootFinished();
         } break;
-        case REVOKE_GPU: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            reply->writeInt32( revokeGPU() );
-        } break;
         case SIGNAL: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             signal();
@@ -209,27 +175,6 @@
             sp<IBinder> b = getCblk()->asBinder();
             reply->writeStrongBinder(b);
         } break;
-        case REQUEST_GPU: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            // TODO: this should be protected by a permission
-            gpu_info_t info;
-            sp<IGPUCallback> callback
-                = interface_cast<IGPUCallback>(data.readStrongBinder());
-            status_t res = requestGPU(callback, &info);
-
-            // FIXME: for now, we don't dynamically allocate the regions array
-            size_t maxCount = sizeof(info.regions)/sizeof(*info.regions);
-            if (info.count > maxCount)
-                return BAD_VALUE;
-
-            reply->writeStrongBinder(info.regs->asBinder());
-            reply->writeInt32(info.count);
-            for (size_t i=0 ; i<info.count ; i++) {
-                reply->writeStrongBinder(info.regions[i].region->asBinder());
-                reply->writeInt32(info.regions[i].reserved);
-            }
-            reply->writeInt32(res);
-        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
@@ -238,41 +183,4 @@
 
 // ----------------------------------------------------------------------------
 
-enum {
-    // Note: BOOT_FINISHED must remain this value, it is called by ActivityManagerService.
-    GPU_LOST = IBinder::FIRST_CALL_TRANSACTION
-};
-
-class BpGPUCallback : public BpInterface<IGPUCallback>
-{
-public:
-    BpGPUCallback(const sp<IBinder>& impl)
-        : BpInterface<IGPUCallback>(impl)
-    {
-    }
-
-    virtual void gpuLost()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGPUCallback::getInterfaceDescriptor());
-        remote()->transact(GPU_LOST, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(GPUCallback, "android.ui.IGPUCallback");
-
-status_t BnGPUCallback::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case GPU_LOST: {
-            CHECK_INTERFACE(IGPUCallback, data, reply);
-            gpuLost();
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
 };
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
index 329bd6e..46c12af 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -192,8 +192,6 @@
 {
     token = parcel.readInt32();
     identity  = parcel.readInt32();
-    heap[0] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
-    heap[1] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
     return NO_ERROR;
 }
 
@@ -201,8 +199,6 @@
 {
     parcel->writeInt32(token);
     parcel->writeInt32(identity);
-    parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL);
-    parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL);
     return NO_ERROR;
 }
 
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 26e694a..2e6b241 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -16,295 +16,653 @@
 
 #define LOG_TAG "Region"
 
-#include <stdio.h>
-#include <utils/Atomic.h>
-#include <utils/Debug.h>
+#include <utils/Log.h>
 #include <utils/String8.h>
+
+#include <ui/Rect.h>
 #include <ui/Region.h>
+#include <ui/Point.h>
+
+#include <private/ui/RegionHelper.h>
+
+// ----------------------------------------------------------------------------
+#define VALIDATE_REGIONS        (false)
+#define VALIDATE_WITH_CORECG    (false)
+// ----------------------------------------------------------------------------
+
+#if VALIDATE_WITH_CORECG
+#include <core/SkRegion.h>
+#endif
 
 namespace android {
+// ----------------------------------------------------------------------------
+
+enum {
+    op_nand = region_operator<Rect>::op_nand,
+    op_and  = region_operator<Rect>::op_and,
+    op_or   = region_operator<Rect>::op_or,
+    op_xor  = region_operator<Rect>::op_xor
+};
 
 // ----------------------------------------------------------------------------
 
 Region::Region()
+    : mBounds(0,0)
 {
 }
 
 Region::Region(const Region& rhs)
-    : mRegion(rhs.mRegion)
+    : mBounds(rhs.mBounds), mStorage(rhs.mStorage)
 {
 }
 
-Region::Region(const SkRegion& rhs)
-    : mRegion(rhs)
+Region::Region(const Rect& rhs)
+    : mBounds(rhs)
 {
 }
 
+Region::Region(const Parcel& parcel)
+{
+    status_t err = read(parcel);
+    LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
+}
+
+Region::Region(const void* buffer)
+{
+    status_t err = read(buffer);
+    LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
+}
+
 Region::~Region()
 {
 }
 
-Region::Region(const Rect& rhs)
-{
-    set(rhs);
-}
-
-Region::Region(const Parcel& parcel)
-{
-    read(parcel);
-}
-
-Region::Region(const void* buffer)
-{
-    read(buffer);
-}
-
 Region& Region::operator = (const Region& rhs)
 {
-    mRegion = rhs.mRegion;
+#if VALIDATE_REGIONS
+    validate(rhs, "operator=");
+#endif
+    mBounds = rhs.mBounds;
+    mStorage = rhs.mStorage;
     return *this;
 }
 
-const SkRegion& Region::toSkRegion() const
-{
-    return mRegion;
-}
-
-Rect Region::bounds() const
-{
-    const SkIRect& b(mRegion.getBounds());
-    return Rect(b.fLeft, b.fTop, b.fRight, b.fBottom);
-}
-
 void Region::clear()
 {
-    mRegion.setEmpty();
+    mBounds.clear();
+    mStorage.clear();
 }
 
 void Region::set(const Rect& r)
 {
-    SkIRect ir;
-    ir.set(r.left, r.top, r.right, r.bottom);
-    mRegion.setRect(ir);
+    mBounds = r;
+    mStorage.clear();
+}
+
+void Region::set(uint32_t w, uint32_t h)
+{
+    mBounds = Rect(int(w), int(h));
+    mStorage.clear();
 }
 
 // ----------------------------------------------------------------------------
 
-Region& Region::orSelf(const Rect& r)
+void Region::addRectUnchecked(int l, int t, int r, int b)
 {
-    SkIRect ir;
-    ir.set(r.left, r.top, r.right, r.bottom);
-    mRegion.op(ir, SkRegion::kUnion_Op);
-    return *this;
+    mStorage.add(Rect(l,t,r,b));
+#if VALIDATE_REGIONS
+    validate(*this, "addRectUnchecked");
+#endif
 }
 
-Region& Region::andSelf(const Rect& r)
-{
-    SkIRect ir;
-    ir.set(r.left, r.top, r.right, r.bottom);
-    mRegion.op(ir, SkRegion::kIntersect_Op);
+// ----------------------------------------------------------------------------
+
+Region& Region::orSelf(const Rect& r) {
+    return operationSelf(r, op_or);
+}
+Region& Region::andSelf(const Rect& r) {
+    return operationSelf(r, op_and);
+}
+Region& Region::subtractSelf(const Rect& r) {
+    return operationSelf(r, op_nand);
+}
+Region& Region::operationSelf(const Rect& r, int op) {
+    Region lhs(*this);
+    boolean_operation(op, *this, lhs, r);
     return *this;
 }
 
 // ----------------------------------------------------------------------------
 
 Region& Region::orSelf(const Region& rhs) {
-    mRegion.op(rhs.mRegion, SkRegion::kUnion_Op);
-    return *this;
+    return operationSelf(rhs, op_or);
 }
-
 Region& Region::andSelf(const Region& rhs) {
-    mRegion.op(rhs.mRegion, SkRegion::kIntersect_Op);
-    return *this;
+    return operationSelf(rhs, op_and);
 }
-
 Region& Region::subtractSelf(const Region& rhs) {
-    mRegion.op(rhs.mRegion, SkRegion::kDifference_Op);
+    return operationSelf(rhs, op_nand);
+}
+Region& Region::operationSelf(const Region& rhs, int op) {
+    Region lhs(*this);
+    boolean_operation(op, *this, lhs, rhs);
     return *this;
 }
 
 Region& Region::translateSelf(int x, int y) {
-    if (x|y) mRegion.translate(x, y);
+    if (x|y) translate(*this, x, y);
     return *this;
 }
 
-Region Region::merge(const Region& rhs) const {
+// ----------------------------------------------------------------------------
+
+const Region Region::merge(const Rect& rhs) const {
+    return operation(rhs, op_or);
+}
+const Region Region::intersect(const Rect& rhs) const {
+    return operation(rhs, op_and);
+}
+const Region Region::subtract(const Rect& rhs) const {
+    return operation(rhs, op_nand);
+}
+const Region Region::operation(const Rect& rhs, int op) const {
     Region result;
-    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kUnion_Op);
+    boolean_operation(op, result, *this, rhs);
     return result;
 }
 
-Region Region::intersect(const Region& rhs) const {
+// ----------------------------------------------------------------------------
+
+const Region Region::merge(const Region& rhs) const {
+    return operation(rhs, op_or);
+}
+const Region Region::intersect(const Region& rhs) const {
+    return operation(rhs, op_and);
+}
+const Region Region::subtract(const Region& rhs) const {
+    return operation(rhs, op_nand);
+}
+const Region Region::operation(const Region& rhs, int op) const {
     Region result;
-    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kIntersect_Op);
+    boolean_operation(op, result, *this, rhs);
     return result;
 }
 
-Region Region::subtract(const Region& rhs) const {
+const Region Region::translate(int x, int y) const {
     Region result;
-    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kDifference_Op);
-    return result;
-}
-
-Region Region::translate(int x, int y) const {
-    Region result;
-    mRegion.translate(x, y, &result.mRegion);
+    translate(result, *this, x, y);
     return result;
 }
 
 // ----------------------------------------------------------------------------
 
 Region& Region::orSelf(const Region& rhs, int dx, int dy) {
-    SkRegion r(rhs.mRegion);
-    r.translate(dx, dy);
-    mRegion.op(r, SkRegion::kUnion_Op);
-    return *this;
+    return operationSelf(rhs, dx, dy, op_or);
 }
-
 Region& Region::andSelf(const Region& rhs, int dx, int dy) {
-    SkRegion r(rhs.mRegion);
-    r.translate(dx, dy);
-    mRegion.op(r, SkRegion::kIntersect_Op);
-    return *this;
+    return operationSelf(rhs, dx, dy, op_and);
 }
-
 Region& Region::subtractSelf(const Region& rhs, int dx, int dy) {
-    SkRegion r(rhs.mRegion);
-    r.translate(dx, dy);
-    mRegion.op(r, SkRegion::kDifference_Op);
+    return operationSelf(rhs, dx, dy, op_nand);
+}
+Region& Region::operationSelf(const Region& rhs, int dx, int dy, int op) {
+    Region lhs(*this);
+    boolean_operation(op, *this, lhs, rhs, dx, dy);
     return *this;
 }
 
-Region Region::merge(const Region& rhs, int dx, int dy) const {
-    Region result;
-    SkRegion r(rhs.mRegion);
-    r.translate(dx, dy);
-    result.mRegion.op(mRegion, r, SkRegion::kUnion_Op);
-    return result;
-}
+// ----------------------------------------------------------------------------
 
-Region Region::intersect(const Region& rhs, int dx, int dy) const {
-    Region result;
-    SkRegion r(rhs.mRegion);
-    r.translate(dx, dy);
-    result.mRegion.op(mRegion, r, SkRegion::kIntersect_Op);
-    return result;
+const Region Region::merge(const Region& rhs, int dx, int dy) const {
+    return operation(rhs, dx, dy, op_or);
 }
-
-Region Region::subtract(const Region& rhs, int dx, int dy) const {
+const Region Region::intersect(const Region& rhs, int dx, int dy) const {
+    return operation(rhs, dx, dy, op_and);
+}
+const Region Region::subtract(const Region& rhs, int dx, int dy) const {
+    return operation(rhs, dx, dy, op_nand);
+}
+const Region Region::operation(const Region& rhs, int dx, int dy, int op) const {
     Region result;
-    SkRegion r(rhs.mRegion);
-    r.translate(dx, dy);
-    result.mRegion.op(mRegion, r, SkRegion::kDifference_Op);
+    boolean_operation(op, result, *this, rhs, dx, dy);
     return result;
 }
 
 // ----------------------------------------------------------------------------
 
-Region::iterator::iterator(const Region& r)
-    : mIt(r.mRegion)
+// This is our region rasterizer, which merges rects and spans together
+// to obtain an optimal region.
+class Region::rasterizer : public region_operator<Rect>::region_rasterizer 
 {
+    Rect& bounds;
+    Vector<Rect>& storage;
+    Rect* head;
+    Rect* tail;
+    Vector<Rect> span;
+    Rect* cur;
+public:
+    rasterizer(Region& reg) 
+        : bounds(reg.mBounds), storage(reg.mStorage), head(), tail(), cur() {
+        bounds.top = bounds.bottom = 0;
+        bounds.left   = INT_MAX;
+        bounds.right  = INT_MIN;
+        storage.clear();
+    }
+
+    ~rasterizer() {
+        if (span.size()) {
+            flushSpan();
+        }
+        if (storage.size()) {
+            bounds.top = storage.itemAt(0).top;
+            bounds.bottom = storage.top().bottom;
+            if (storage.size() == 1) {
+                storage.clear();
+            }
+        } else {
+            bounds.left  = 0;
+            bounds.right = 0;
+        }
+    }
+    
+    virtual void operator()(const Rect& rect) {
+        //LOGD(">>> %3d, %3d, %3d, %3d", 
+        //        rect.left, rect.top, rect.right, rect.bottom);
+        if (span.size()) {
+            if (cur->top != rect.top) {
+                flushSpan();
+            } else if (cur->right == rect.left) {
+                cur->right = rect.right;
+                return;
+            }
+        }
+        span.add(rect);
+        cur = span.editArray() + (span.size() - 1);
+    }
+private:
+    template<typename T> 
+    static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; }
+    template<typename T> 
+    static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; }
+    void flushSpan() {
+        bool merge = false;
+        if (tail-head == ssize_t(span.size())) {
+            Rect const* p = cur;
+            Rect const* q = head;
+            if (p->top == q->bottom) {
+                merge = true;
+                while (q != tail) {
+                    if ((p->left != q->left) || (p->right != q->right)) {
+                        merge = false;
+                        break;
+                    }
+                    p++, q++;
+                }
+            }
+        }
+        if (merge) {
+            const int bottom = span[0].bottom;
+            Rect* r = head;
+            while (r != tail) {
+                r->bottom = bottom;
+                r++;
+            }
+        } else {
+            bounds.left = min(span.itemAt(0).left, bounds.left);
+            bounds.right = max(span.top().right, bounds.right);
+            storage.appendVector(span);
+            tail = storage.editArray() + storage.size();
+            head = tail - span.size();
+        }
+        span.clear();
+    }
+};
+
+bool Region::validate(const Region& reg, const char* name)
+{
+    bool result = true;
+    const_iterator cur = reg.begin();
+    const_iterator const tail = reg.end();
+    const_iterator prev = cur++;
+    Rect b(*prev);
+    while (cur != tail) {
+        b.left   = b.left   < cur->left   ? b.left   : cur->left;
+        b.top    = b.top    < cur->top    ? b.top    : cur->top;
+        b.right  = b.right  > cur->right  ? b.right  : cur->right;
+        b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
+        if (cur->top == prev->top) {
+            if (cur->bottom != prev->bottom) {
+                LOGE("%s: invalid span %p", name, cur);
+                result = false;
+            } else if (cur->left < prev->right) {
+                LOGE("%s: spans overlap horizontally prev=%p, cur=%p",
+                        name, prev, cur);
+                result = false;
+            }
+        } else if (cur->top < prev->bottom) {
+            LOGE("%s: spans overlap vertically prev=%p, cur=%p",
+                    name, prev, cur);
+            result = false;
+        }
+        prev = cur;
+        cur++;
+    }
+    if (b != reg.getBounds()) {
+        result = false;
+        LOGE("%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
+                b.left, b.top, b.right, b.bottom,
+                reg.getBounds().left, reg.getBounds().top, 
+                reg.getBounds().right, reg.getBounds().bottom);
+    }
+    if (result == false) {
+        reg.dump(name);
+    }
+    return result;
 }
 
-int Region::iterator::iterate(Rect* rect)
+void Region::boolean_operation(int op, Region& dst,
+        const Region& lhs,
+        const Region& rhs, int dx, int dy)
 {
-    if (mIt.done())
-        return 0;
-    const SkIRect& r(mIt.rect());
-    rect->left  = r.fLeft;
-    rect->top   = r.fTop;
-    rect->right = r.fRight;
-    rect->bottom= r.fBottom;
-    mIt.next();
-    return 1;
+    size_t lhs_count;
+    Rect const * const lhs_rects = lhs.getArray(&lhs_count);
+
+    size_t rhs_count;
+    Rect const * const rhs_rects = rhs.getArray(&rhs_count);
+
+    region_operator<Rect>::region lhs_region(lhs_rects, lhs_count);
+    region_operator<Rect>::region rhs_region(rhs_rects, rhs_count, dx, dy);
+    region_operator<Rect> operation(op, lhs_region, rhs_region);
+    { // scope for rasterizer (dtor has side effects)
+        rasterizer r(dst);
+        operation(r);
+    }
+
+#if VALIDATE_REGIONS
+    validate(lhs, "boolean_operation: lhs");
+    validate(rhs, "boolean_operation: rhs");
+    validate(dst, "boolean_operation: dst");
+#endif
+
+#if VALIDATE_WITH_CORECG
+    SkRegion sk_lhs;
+    SkRegion sk_rhs;
+    SkRegion sk_dst;
+    
+    for (size_t i=0 ; i<lhs_count ; i++)
+        sk_lhs.op(
+                lhs_rects[i].left   + dx,
+                lhs_rects[i].top    + dy,
+                lhs_rects[i].right  + dx,
+                lhs_rects[i].bottom + dy,
+                SkRegion::kUnion_Op);
+    
+    for (size_t i=0 ; i<rhs_count ; i++)
+        sk_rhs.op(
+                rhs_rects[i].left   + dx,
+                rhs_rects[i].top    + dy,
+                rhs_rects[i].right  + dx,
+                rhs_rects[i].bottom + dy,
+                SkRegion::kUnion_Op);
+ 
+    const char* name = "---";
+    SkRegion::Op sk_op;
+    switch (op) {
+        case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break;
+        case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break;
+        case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break;
+    }
+    sk_dst.op(sk_lhs, sk_rhs, sk_op);
+
+    if (sk_dst.isEmpty() && dst.isEmpty())
+        return;
+    
+    bool same = true;
+    Region::const_iterator head = dst.begin();
+    Region::const_iterator const tail = dst.end();
+    SkRegion::Iterator it(sk_dst);
+    while (!it.done()) {
+        if (head != tail) {
+            if (
+                    head->left != it.rect().fLeft ||     
+                    head->top != it.rect().fTop ||     
+                    head->right != it.rect().fRight ||     
+                    head->bottom != it.rect().fBottom
+            ) {
+                same = false;
+                break;
+            }
+        } else {
+            same = false;
+            break;
+        }
+        head++;
+        it.next();
+    }
+    
+    if (head != tail) {
+        same = false;
+    }
+    
+    if(!same) {
+        LOGD("---\nregion boolean %s failed", name);
+        lhs.dump("lhs");
+        rhs.dump("rhs");
+        dst.dump("dst");
+        LOGD("should be");
+        SkRegion::Iterator it(sk_dst);
+        while (!it.done()) {
+            LOGD("    [%3d, %3d, %3d, %3d]",
+                it.rect().fLeft,
+                it.rect().fTop,
+                it.rect().fRight,
+                it.rect().fBottom);
+            it.next();
+        }
+    }
+#endif
+}
+
+void Region::boolean_operation(int op, Region& dst,
+        const Region& lhs,
+        const Rect& rhs, int dx, int dy)
+{
+#if VALIDATE_WITH_CORECG || VALIDATE_REGIONS
+    boolean_operation(op, dst, lhs, Region(rhs), dx, dy);
+#else
+    size_t lhs_count;
+    Rect const * const lhs_rects = lhs.getArray(&lhs_count);
+
+    region_operator<Rect>::region lhs_region(lhs_rects, lhs_count);
+    region_operator<Rect>::region rhs_region(&rhs, 1, dx, dy);
+    region_operator<Rect> operation(op, lhs_region, rhs_region);
+    { // scope for rasterizer (dtor has side effects)
+        rasterizer r(dst);
+        operation(r);
+    }
+
+#endif
+}
+
+void Region::boolean_operation(int op, Region& dst,
+        const Region& lhs, const Region& rhs)
+{
+    boolean_operation(op, dst, lhs, rhs, 0, 0);
+}
+
+void Region::boolean_operation(int op, Region& dst,
+        const Region& lhs, const Rect& rhs)
+{
+    boolean_operation(op, dst, lhs, rhs, 0, 0);
+}
+
+void Region::translate(Region& reg, int dx, int dy)
+{
+    if (!reg.isEmpty()) {
+#if VALIDATE_REGIONS
+        validate(reg, "translate (before)");
+#endif
+        reg.mBounds.translate(dx, dy);
+        size_t count = reg.mStorage.size();
+        Rect* rects = reg.mStorage.editArray();
+        while (count) {
+            rects->translate(dx, dy);
+            rects++;
+            count--;
+        }
+#if VALIDATE_REGIONS
+        validate(reg, "translate (after)");
+#endif
+    }
+}
+
+void Region::translate(Region& dst, const Region& reg, int dx, int dy)
+{
+    dst = reg;
+    translate(dst, dx, dy);
 }
 
 // ----------------------------------------------------------------------------
 
-// we write a 4byte size ahead of the actual region, so we know how much we'll need for reading
-
 status_t Region::write(Parcel& parcel) const
 {
-    int32_t size = mRegion.flatten(NULL);
-    parcel.writeInt32(size);
-    mRegion.flatten(parcel.writeInplace(size));
+#if VALIDATE_REGIONS
+    validate(*this, "write(Parcel)");
+#endif
+    status_t err;
+    const size_t count = mStorage.size();
+    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
+    void* buffer = parcel.writeInplace(sizeNeeded);
+    if (!buffer) return NO_MEMORY;
+    ssize_t written = Region::write(buffer, sizeNeeded);
+    if (written < 0) return status_t(written);
     return NO_ERROR;
 }
 
 status_t Region::read(const Parcel& parcel)
 {
-    size_t size = parcel.readInt32();
-    mRegion.unflatten(parcel.readInplace(size));
+    void const* buffer = parcel.readInplace(sizeof(int32_t));
+    if (!buffer) return NO_MEMORY;
+    const size_t count = *static_cast<int32_t const *>(buffer);
+    void const* dummy = parcel.readInplace((1+count)*sizeof(Rect));
+    if (!dummy) return NO_MEMORY;
+    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
+    const ssize_t read = Region::read(buffer);
+    if (read < 0) return status_t(read);
+#if VALIDATE_REGIONS
+    validate(*this, "read(Parcel)");
+#endif
     return NO_ERROR;
 }
 
 ssize_t Region::write(void* buffer, size_t size) const
 {
-    size_t sizeNeeded = mRegion.flatten(NULL);
+#if VALIDATE_REGIONS
+    validate(*this, "write(buffer)");
+#endif
+    const size_t count = mStorage.size();
+    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
     if (sizeNeeded > size) return NO_MEMORY;
-    return mRegion.flatten(buffer);
+    int32_t* const p = static_cast<int32_t*>(buffer); 
+    *p = count;
+    memcpy(p+1, &mBounds, sizeof(Rect));
+    if (count) {
+        memcpy(p+5, mStorage.array(), count*sizeof(Rect));
+    }
+    return ssize_t(sizeNeeded);
 }
 
 ssize_t Region::read(const void* buffer)
 {
-    return mRegion.unflatten(buffer);
+    int32_t const* const p = static_cast<int32_t const*>(buffer); 
+    const size_t count = *p;
+    memcpy(&mBounds, p+1, sizeof(Rect));
+    mStorage.clear();
+    if (count) {
+        mStorage.insertAt(0, count);
+        memcpy(mStorage.editArray(), p+5, count*sizeof(Rect));
+    }
+#if VALIDATE_REGIONS
+    validate(*this, "read(buffer)");
+#endif
+    return ssize_t(sizeof(int32_t) + (1+count)*sizeof(Rect));
 }
 
 ssize_t Region::writeEmpty(void* buffer, size_t size)
 {
-    if (size < 4) return NO_MEMORY;
-    // this needs to stay in sync with SkRegion
-    *static_cast<int32_t*>(buffer) = -1;
-    return 4;
+    const size_t sizeNeeded = sizeof(int32_t) + sizeof(Rect);
+    if (sizeNeeded > size) return NO_MEMORY;
+    int32_t* const p = static_cast<int32_t*>(buffer); 
+    memset(p, 0, sizeNeeded);
+    return ssize_t(sizeNeeded);
 }
 
 bool Region::isEmpty(void* buffer)
 {
-    // this needs to stay in sync with SkRegion
-    return *static_cast<int32_t*>(buffer) == -1;
+    int32_t const* const p = static_cast<int32_t const*>(buffer); 
+    Rect const* const b = reinterpret_cast<Rect const *>(p+1);
+    return b->isEmpty();
 }
 
-size_t Region::rects(Vector<Rect>& rectList) const
+// ----------------------------------------------------------------------------
+
+Region::const_iterator Region::begin() const {
+    return isRect() ? &mBounds : mStorage.array();
+}
+
+Region::const_iterator Region::end() const {
+    return isRect() ? ((&mBounds) + 1) : (mStorage.array() + mStorage.size());
+}
+
+Rect const* Region::getArray(size_t* count) const {
+    const_iterator const b(begin());
+    const_iterator const e(end());
+    if (count) *count = e-b;
+    return b;
+}
+
+size_t Region::getRects(Vector<Rect>& rectList) const
 {
-    rectList.clear();
-    if (!isEmpty()) {
-        SkRegion::Iterator iterator(mRegion);
-        while( !iterator.done() ) {
-            const SkIRect& ir(iterator.rect());
-            rectList.push(Rect(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom));
-            iterator.next();
-        }
+    rectList = mStorage;
+    if (rectList.isEmpty()) {
+        rectList.clear();
+        rectList.add(mBounds);
     }
     return rectList.size();
 }
 
+// ----------------------------------------------------------------------------
+
 void Region::dump(String8& out, const char* what, uint32_t flags) const
 {
     (void)flags;
-    Vector<Rect> r;
-    rects(r);
-    
+    const_iterator head = begin();
+    const_iterator const tail = end();
+
     size_t SIZE = 256;
     char buffer[SIZE];
-    
-    snprintf(buffer, SIZE, "  Region %s (this=%p, count=%d)\n", what, this, r.size());
+
+    snprintf(buffer, SIZE, "  Region %s (this=%p, count=%d)\n",
+            what, this, tail-head);
     out.append(buffer);
-    for (size_t i=0 ; i<r.size() ; i++) {
+    while (head != tail) {
         snprintf(buffer, SIZE, "    [%3d, %3d, %3d, %3d]\n",
-            r[i].left, r[i].top,r[i].right,r[i].bottom);
+                head->left, head->top, head->right, head->bottom);
         out.append(buffer);
+        head++;
     }
 }
 
 void Region::dump(const char* what, uint32_t flags) const
 {
     (void)flags;
-    Vector<Rect> r;
-    rects(r);
-    LOGD("  Region %s (this=%p, count=%d)\n", what, this, r.size());
-    for (size_t i=0 ; i<r.size() ; i++) {
+    const_iterator head = begin();
+    const_iterator const tail = end();
+    LOGD("  Region %s (this=%p, count=%d)\n", what, this, tail-head);
+    while (head != tail) {
         LOGD("    [%3d, %3d, %3d, %3d]\n",
-            r[i].left, r[i].top,r[i].right,r[i].bottom);
+                head->left, head->top, head->right, head->bottom);
+        head++;
     }
 }
 
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 05cc529..b8b428f 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -23,202 +23,319 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <utils/Atomic.h>
 #include <utils/Errors.h>
 #include <utils/threads.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IMemory.h>
 #include <utils/Log.h>
 
+#include <ui/DisplayInfo.h>
+#include <ui/BufferMapper.h>
 #include <ui/ISurface.h>
 #include <ui/Surface.h>
 #include <ui/SurfaceComposerClient.h>
 #include <ui/Rect.h>
 
+#include <pixelflinger/pixelflinger.h>
+
 #include <private/ui/SharedState.h>
 #include <private/ui/LayerState.h>
+#include <private/ui/SurfaceBuffer.h>
 
 namespace android {
 
-// ---------------------------------------------------------------------------
+// ============================================================================
+//  SurfaceBuffer
+// ============================================================================
 
-Surface::Surface(const sp<SurfaceComposerClient>& client, 
+SurfaceBuffer::SurfaceBuffer() 
+    : BASE(), mOwner(false), mBufferMapper(BufferMapper::get())
+{
+    width  = 
+    height = 
+    stride = 
+    format = 
+    usage  = 0;
+    handle = NULL;
+}
+
+SurfaceBuffer::SurfaceBuffer(const Parcel& data) 
+    : BASE(), mOwner(true), mBufferMapper(BufferMapper::get())
+{
+    // we own the handle in this case
+    width  = data.readInt32();
+    height = data.readInt32();
+    stride = data.readInt32();
+    format = data.readInt32();
+    usage  = data.readInt32();
+    handle = data.readNativeHandle();
+}
+
+SurfaceBuffer::~SurfaceBuffer()
+{
+    if (handle && mOwner) {
+        native_handle_close(handle);
+        native_handle_delete(const_cast<native_handle*>(handle));
+    }
+}
+
+status_t SurfaceBuffer::lock(uint32_t usage, void** vaddr)
+{
+    const Rect lockBounds(width, height);
+    status_t res = lock(usage, lockBounds, vaddr);
+    return res;
+}
+
+status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
+{
+    status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
+    return res;
+}
+
+status_t SurfaceBuffer::unlock()
+{
+    status_t res = getBufferMapper().unlock(handle);
+    return res;
+}
+
+status_t SurfaceBuffer::writeToParcel(Parcel* reply, 
+        android_native_buffer_t const* buffer)
+{
+    reply->writeInt32(buffer->width);
+    reply->writeInt32(buffer->height);
+    reply->writeInt32(buffer->stride);
+    reply->writeInt32(buffer->format);
+    reply->writeInt32(buffer->usage);
+    reply->writeNativeHandle(buffer->handle);
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------
+
+static void copyBlt(
+        const sp<SurfaceBuffer>& dst, 
+        const sp<SurfaceBuffer>& src, 
+        const Region& reg)
+{
+    uint8_t const * src_bits;
+    src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
+
+    uint8_t* dst_bits;
+    dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits);
+    
+    size_t c;
+    Rect const* const rects = reg.getArray(&c);
+    
+    if (c) {
+        // NOTE: dst and src must be the same format
+        const size_t bpp = bytesPerPixel(src->format);
+        const size_t dbpr = dst->stride * bpp;
+        const size_t sbpr = src->stride * bpp;
+
+        for (size_t i=0 ; i<c ; i++) {
+            const Rect& r = rects[i];
+            ssize_t h = r.height();
+            if (h <= 0) continue;
+            size_t size = r.width() * 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);
+        }
+    }
+    
+    src->unlock();
+    dst->unlock();
+}
+
+// ============================================================================
+//  SurfaceControl
+// ============================================================================
+
+SurfaceControl::SurfaceControl(
+        const sp<SurfaceComposerClient>& client, 
         const sp<ISurface>& surface,
         const ISurfaceFlingerClient::surface_data_t& data,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
-        bool owner)
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
     : mClient(client), mSurface(surface),
       mToken(data.token), mIdentity(data.identity),
-      mFormat(format), mFlags(flags), mOwner(owner)
+      mFormat(format), mFlags(flags)
 {
-    mSwapRectangle.makeInvalid();
-    mSurfaceHeapBase[0] = 0;
-    mSurfaceHeapBase[1] = 0;
-    mHeap[0] = data.heap[0]; 
-    mHeap[1] = data.heap[1];
+}
+        
+SurfaceControl::~SurfaceControl()
+{
+    destroy();
 }
 
-Surface::Surface(Surface const* rhs)
-    : mOwner(false)
+void SurfaceControl::destroy()
 {
-    mToken   = rhs->mToken;
-    mIdentity= rhs->mIdentity;
-    mClient  = rhs->mClient;
-    mSurface = rhs->mSurface;
-    mHeap[0] = rhs->mHeap[0];
-    mHeap[1] = rhs->mHeap[1];
-    mFormat  = rhs->mFormat;
-    mFlags   = rhs->mFlags;
-    mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0];
-    mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1];
-    mSwapRectangle.makeInvalid();
-}
-
-Surface::~Surface()
-{
-    if (mOwner && mToken>=0 && mClient!=0) {
+    if (isValid()) {
         mClient->destroySurface(mToken);
     }
+
+    // clear all references and trigger an IPC now, to make sure things
+    // happen without delay, since these resources are quite heavy.
     mClient.clear();
     mSurface.clear();
-    mHeap[0].clear();
-    mHeap[1].clear();
     IPCThreadState::self()->flushCommands();
 }
 
-sp<Surface> Surface::dup() const
+void SurfaceControl::clear() 
 {
-    Surface const * r = this;
-    if (this && mOwner) {
-        // the only reason we need to do this is because of Java's garbage
-        // collector: because we're creating a copy of the Surface
-        // instead of a reference, we can garantee that when our last
-        // reference goes away, the real surface will be deleted.
-        // Without this hack (the code is correct too), we'd have to
-        // wait for a GC for the surface to go away.
-        r = new Surface(this);        
+    // here, the window manager tells us explicitly that we should destroy
+    // the surface's resource. Soon after this call, it will also release
+    // its last reference (which will call the dtor); however, it is possible
+    // that a client living in the same process still holds references which
+    // would delay the call to the dtor -- that is why we need this explicit
+    // "clear()" call.
+    destroy();
+}
+
+bool SurfaceControl::isSameSurface(
+        const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) 
+{
+    if (lhs == 0 || rhs == 0)
+        return false;
+    return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
+}
+
+status_t SurfaceControl::setLayer(int32_t layer) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setLayer(mToken, layer);
+}
+status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setPosition(mToken, x, y);
+}
+status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setSize(mToken, w, h);
+}
+status_t SurfaceControl::hide() {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->hide(mToken);
+}
+status_t SurfaceControl::show(int32_t layer) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->show(mToken, layer);
+}
+status_t SurfaceControl::freeze() {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->freeze(mToken);
+}
+status_t SurfaceControl::unfreeze() {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->unfreeze(mToken);
+}
+status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setFlags(mToken, flags, mask);
+}
+status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setTransparentRegionHint(mToken, transparent);
+}
+status_t SurfaceControl::setAlpha(float alpha) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setAlpha(mToken, alpha);
+}
+status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
+}
+status_t SurfaceControl::setFreezeTint(uint32_t tint) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setFreezeTint(mToken, tint);
+}
+
+status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
+{
+    if (mToken<0 || mClient==0) {
+        LOGE("invalid token (%d, identity=%u) or client (%p)", 
+                mToken, mIdentity, mClient.get());
+        return NO_INIT;
     }
-    return const_cast<Surface*>(r);
+    if (cblk == 0) {
+        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
+        return NO_INIT;
+    }
+    status_t err = cblk->validate(mToken);
+    if (err != NO_ERROR) {
+        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+                mToken, mIdentity, err, strerror(-err));
+        return err;
+    }
+    if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
+        LOGE("using an invalid surface id=%d, identity=%u should be %d",
+                mToken, mIdentity, cblk->layers[mToken].identity);
+        return NO_INIT;
+    }
+    return NO_ERROR;
 }
 
-status_t Surface::nextBuffer(SurfaceInfo* info) {
-    return mClient->nextBuffer(this, info);
-}
-
-status_t Surface::lock(SurfaceInfo* info, bool blocking) {
-    return Surface::lock(info, NULL, blocking);
-}
-
-status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->lockSurface(this, info, dirty, blocking);
-}
-
-status_t Surface::unlockAndPost() {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->unlockAndPostSurface(this);
-}
-
-status_t Surface::unlock() {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->unlockSurface(this);
-}
-
-status_t Surface::setLayer(int32_t layer) {
-    return mClient->setLayer(this, layer);
-}
-status_t Surface::setPosition(int32_t x, int32_t y) {
-    return mClient->setPosition(this, x, y);
-}
-status_t Surface::setSize(uint32_t w, uint32_t h) {
-    return mClient->setSize(this, w, h);
-}
-status_t Surface::hide() {
-    return mClient->hide(this);
-}
-status_t Surface::show(int32_t layer) {
-    return mClient->show(this, layer);
-}
-status_t Surface::freeze() {
-    return mClient->freeze(this);
-}
-status_t Surface::unfreeze() {
-    return mClient->unfreeze(this);
-}
-status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
-    return mClient->setFlags(this, flags, mask);
-}
-status_t Surface::setTransparentRegionHint(const Region& transparent) {
-    return mClient->setTransparentRegionHint(this, transparent);
-}
-status_t Surface::setAlpha(float alpha) {
-    return mClient->setAlpha(this, alpha);
-}
-status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
-    return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy);
-}
-status_t Surface::setFreezeTint(uint32_t tint) {
-    return mClient->setFreezeTint(this, tint);
-}
-
-Region Surface::dirtyRegion() const  {
-    return mDirtyRegion; 
-}
-void Surface::setDirtyRegion(const Region& region) const {
-    mDirtyRegion = region;
-}
-const Rect& Surface::swapRectangle() const {
-    return mSwapRectangle;
-}
-void Surface::setSwapRectangle(const Rect& r) {
-    mSwapRectangle = r;
-}
-
-sp<Surface> Surface::readFromParcel(Parcel* parcel)
+status_t SurfaceControl::writeSurfaceToParcel(
+        const sp<SurfaceControl>& control, Parcel* parcel)
 {
-    sp<SurfaceComposerClient> client;
-    ISurfaceFlingerClient::surface_data_t data;
-    sp<IBinder> clientBinder= parcel->readStrongBinder();
-    sp<ISurface> surface    = interface_cast<ISurface>(parcel->readStrongBinder());
-    data.heap[0]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
-    data.heap[1]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
-    data.token              = parcel->readInt32();
-    data.identity           = parcel->readInt32();
-    PixelFormat format      = parcel->readInt32();
-    uint32_t flags          = parcel->readInt32();
-
-    if (clientBinder != NULL)
-        client = SurfaceComposerClient::clientForConnection(clientBinder);
-
-    return new Surface(client, surface, data, 0, 0, format, flags, false);
-}
-
-status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel)
-{
-    uint32_t flags=0;
-    uint32_t format=0;
+    uint32_t flags = 0;
+    uint32_t format = 0;
     SurfaceID token = -1;
     uint32_t identity = 0;
     sp<SurfaceComposerClient> client;
     sp<ISurface> sur;
-    sp<IMemoryHeap> heap[2];
-    if (surface->isValid()) {
-        token = surface->mToken;
-        identity = surface->mIdentity;
-        client = surface->mClient;
-        sur = surface->mSurface;
-        heap[0] = surface->mHeap[0];
-        heap[1] = surface->mHeap[1];
-        format = surface->mFormat;
-        flags = surface->mFlags;
+    if (SurfaceControl::isValid(control)) {
+        token    = control->mToken;
+        identity = control->mIdentity;
+        client   = control->mClient;
+        sur      = control->mSurface;
+        format   = control->mFormat;
+        flags    = control->mFlags;
     }
     parcel->writeStrongBinder(client!=0  ? client->connection() : NULL);
     parcel->writeStrongBinder(sur!=0     ? sur->asBinder()      : NULL);
-    parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder()  : NULL);
-    parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder()  : NULL);
     parcel->writeInt32(token);
     parcel->writeInt32(identity);
     parcel->writeInt32(format);
@@ -226,30 +343,348 @@
     return NO_ERROR;
 }
 
-bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) 
+sp<Surface> SurfaceControl::getSurface() const
+{
+    Mutex::Autolock _l(mLock);
+    if (mSurfaceData == 0) {
+        mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
+    }
+    return mSurfaceData;
+}
+
+// ============================================================================
+//  Surface
+// ============================================================================
+
+Surface::Surface(const sp<SurfaceControl>& surface)
+    : mClient(surface->mClient), mSurface(surface->mSurface),
+      mToken(surface->mToken), mIdentity(surface->mIdentity),
+      mFormat(surface->mFormat), mFlags(surface->mFlags),
+      mBufferMapper(BufferMapper::get())
+{
+    init();
+}
+
+Surface::Surface(const Parcel& parcel)
+    :  mBufferMapper(BufferMapper::get())
+{
+    sp<IBinder> clientBinder = parcel.readStrongBinder();
+    mSurface    = interface_cast<ISurface>(parcel.readStrongBinder());
+    mToken      = parcel.readInt32();
+    mIdentity   = parcel.readInt32();
+    mFormat     = parcel.readInt32();
+    mFlags      = parcel.readInt32();
+
+    if (clientBinder != NULL)
+        mClient = SurfaceComposerClient::clientForConnection(clientBinder);
+
+    init();
+}
+
+void Surface::init()
+{
+    android_native_window_t::setSwapInterval  = setSwapInterval;
+    android_native_window_t::dequeueBuffer    = dequeueBuffer;
+    android_native_window_t::lockBuffer       = lockBuffer;
+    android_native_window_t::queueBuffer      = queueBuffer;
+    mSwapRectangle.makeInvalid();
+    DisplayInfo dinfo;
+    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
+    const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
+    const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
+    // FIXME: set real values here
+    const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
+    const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
+    const_cast<uint32_t&>(android_native_window_t::flags) = 0;
+}
+
+
+Surface::~Surface()
+{
+    // this is a client-side operation, the surface is destroyed, unmap
+    // its buffers in this process.
+    for (int i=0 ; i<2 ; i++) {
+        if (mBuffers[i] != 0) {
+            getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
+        }
+    }
+
+    // clear all references and trigger an IPC now, to make sure things
+    // happen without delay, since these resources are quite heavy.
+    mClient.clear();
+    mSurface.clear();
+    IPCThreadState::self()->flushCommands();
+}
+
+status_t Surface::validate(per_client_cblk_t const* cblk) const
+{
+    if (mToken<0 || mClient==0) {
+        LOGE("invalid token (%d, identity=%u) or client (%p)", 
+                mToken, mIdentity, mClient.get());
+        return NO_INIT;
+    }
+    if (cblk == 0) {
+        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
+        return NO_INIT;
+    }
+    status_t err = cblk->validate(mToken);
+    if (err != NO_ERROR) {
+        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+                mToken, mIdentity, err, strerror(-err));
+        return err;
+    }
+    if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
+        LOGE("using an invalid surface id=%d, identity=%u should be %d",
+                mToken, mIdentity, cblk->layers[mToken].identity);
+        return NO_INIT;
+    }
+    return NO_ERROR;
+}
+
+
+bool Surface::isSameSurface(
+        const sp<Surface>& lhs, const sp<Surface>& rhs) 
 {
     if (lhs == 0 || rhs == 0)
         return false;
     return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
 }
 
-void* Surface::heapBase(int i) const 
+// ----------------------------------------------------------------------------
+
+int Surface::setSwapInterval(android_native_window_t* window, int interval)
 {
-    void* heapBase = mSurfaceHeapBase[i];
-    // map lazily so it doesn't get mapped in clients that don't need it
-    if (heapBase == 0) {
-        const sp<IMemoryHeap>& heap(mHeap[i]);
-        if (heap != 0) {
-            heapBase = static_cast<uint8_t*>(heap->base());
-            if (heapBase == MAP_FAILED) {
-                heapBase = NULL;
-                LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)",
-                        heap->asBinder().get(), heap.get());
+    return 0;
+}
+
+int Surface::dequeueBuffer(android_native_window_t* window, 
+        android_native_buffer_t** buffer)
+{
+    Surface* self = getSelf(window);
+    return self->dequeueBuffer(buffer);
+}
+
+int Surface::lockBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    Surface* self = getSelf(window);
+    return self->lockBuffer(buffer);
+}
+
+int Surface::queueBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    Surface* self = getSelf(window);
+    return self->queueBuffer(buffer);
+}
+
+// ----------------------------------------------------------------------------
+
+status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
+{
+    android_native_buffer_t* out;
+    status_t err = dequeueBuffer(&out);
+    *buffer = SurfaceBuffer::getSelf(out);
+    return err;
+}
+
+status_t Surface::lockBuffer(const sp<SurfaceBuffer>& buffer)
+{
+    return lockBuffer(buffer.get());
+}
+
+status_t Surface::queueBuffer(const sp<SurfaceBuffer>& buffer)
+{
+    return queueBuffer(buffer.get());
+}
+
+// ----------------------------------------------------------------------------
+
+int Surface::dequeueBuffer(android_native_buffer_t** buffer)
+{
+    // FIXME: dequeueBuffer() needs proper implementation
+
+    Mutex::Autolock _l(mSurfaceLock);
+
+    per_client_cblk_t* const cblk = mClient->mControl;
+    status_t err = validate(cblk);
+    if (err != NO_ERROR)
+        return err;
+
+    SurfaceID index(mToken); 
+    
+    int32_t backIdx = cblk->lock_layer(size_t(index),
+            per_client_cblk_t::BLOCKING);
+
+    if (backIdx < 0)
+        return status_t(backIdx); 
+
+    mBackbufferIndex = backIdx;
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+
+    volatile const surface_info_t* const back = lcblk->surface + backIdx;
+    if (back->flags & surface_info_t::eNeedNewBuffer) {
+        getBufferLocked(backIdx);
+    }
+
+    const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+    mDirtyRegion.set(backBuffer->width, backBuffer->height);
+    *buffer = backBuffer.get();
+  
+    return NO_ERROR;
+}
+
+int Surface::lockBuffer(android_native_buffer_t* buffer)
+{
+    Mutex::Autolock _l(mSurfaceLock);
+
+    per_client_cblk_t* const cblk = mClient->mControl;
+    status_t err = validate(cblk);
+    if (err != NO_ERROR)
+        return err;
+
+    // FIXME: lockBuffer() needs proper implementation
+    return 0;
+}
+
+int Surface::queueBuffer(android_native_buffer_t* buffer)
+{   
+    Mutex::Autolock _l(mSurfaceLock);
+
+    per_client_cblk_t* const cblk = mClient->mControl;
+    status_t err = validate(cblk);
+    if (err != NO_ERROR)
+        return err;
+
+    if (mSwapRectangle.isValid()) {
+        mDirtyRegion.set(mSwapRectangle);
+    }
+    
+    // transmit the dirty region
+    SurfaceID index(mToken); 
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+    _send_dirty_region(lcblk, mDirtyRegion);
+
+    uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
+    if (!(newstate & eNextFlipPending))
+        mClient->signalServer();
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+status_t Surface::lock(SurfaceInfo* info, bool blocking) {
+    return Surface::lock(info, NULL, blocking);
+}
+
+status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
+{
+    // FIXME: needs some locking here
+    
+    sp<SurfaceBuffer> backBuffer;
+    status_t err = dequeueBuffer(&backBuffer);
+    if (err == NO_ERROR) {
+        err = lockBuffer(backBuffer);
+        if (err == NO_ERROR) {
+            // we handle copy-back here...
+            
+            const Rect bounds(backBuffer->width, backBuffer->height);
+            Region scratch(bounds);
+            Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
+
+            per_client_cblk_t* const cblk = mClient->mControl;
+            layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
+            volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
+            if (back->flags & surface_info_t::eBufferDirty) {
+                // content is meaningless in this case and the whole surface
+                // needs to be redrawn.
+                newDirtyRegion.set(bounds);
+            } else {
+                newDirtyRegion.andSelf(bounds);
+                if (!(lcblk->flags & eNoCopyBack)) {
+                    const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
+                    const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
+                    if (!copyback.isEmpty() && frontBuffer!=0) {
+                        // copy front to back
+                        copyBlt(backBuffer, frontBuffer, copyback);
+                    }
+                }
             }
-            mSurfaceHeapBase[i] = heapBase;
+            mDirtyRegion = newDirtyRegion;
+            mOldDirtyRegion = newDirtyRegion;
+
+            void* vaddr;
+            status_t res = backBuffer->lock(
+                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                    newDirtyRegion.bounds(), &vaddr);
+            
+            LOGW_IF(res, "failed locking buffer %d (%p)", 
+                    mBackbufferIndex, backBuffer->handle);
+
+            mLockedBuffer = backBuffer;
+            other->w      = backBuffer->width;
+            other->h      = backBuffer->height;
+            other->s      = backBuffer->stride;
+            other->usage  = backBuffer->usage;
+            other->format = backBuffer->format;
+            other->bits   = vaddr;
         }
     }
-    return heapBase;
+    return err;
+}
+    
+status_t Surface::unlockAndPost() 
+{
+    // FIXME: needs some locking here
+
+    if (mLockedBuffer == 0)
+        return BAD_VALUE;
+
+    status_t res = mLockedBuffer->unlock();
+    LOGW_IF(res, "failed unlocking buffer %d (%p)",
+            mBackbufferIndex, mLockedBuffer->handle);
+    
+    status_t err = queueBuffer(mLockedBuffer);
+    mLockedBuffer = 0;
+    return err;
+}
+
+void Surface::_send_dirty_region(
+        layer_cblk_t* lcblk, const Region& dirty)
+{
+    const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
+    flat_region_t* flat_region = lcblk->region + index;
+    status_t err = dirty.write(flat_region, sizeof(flat_region_t));
+    if (err < NO_ERROR) {
+        // region doesn't fit, use the bounds
+        const Region reg(dirty.bounds());
+        reg.write(flat_region, sizeof(flat_region_t));
+    }
+}
+
+void Surface::setSwapRectangle(const Rect& r) {
+    mSwapRectangle = r;
+}
+
+status_t Surface::getBufferLocked(int index)
+{
+    status_t err = NO_MEMORY;
+    sp<SurfaceBuffer> buffer = mSurface->getBuffer();
+    LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
+    if (buffer != 0) {
+        sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
+        if (currentBuffer != 0) {
+            getBufferMapper().unregisterBuffer(currentBuffer->handle);
+            currentBuffer.clear();
+        }
+        err = getBufferMapper().registerBuffer(buffer->handle);
+        LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
+        if (err == NO_ERROR) {
+            currentBuffer = buffer;
+        }
+    }
+    return err; 
 }
 
 }; // namespace android
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp
index 8acd2ee..025bf6e3 100644
--- a/libs/ui/SurfaceComposerClient.cpp
+++ b/libs/ui/SurfaceComposerClient.cpp
@@ -29,27 +29,21 @@
 #include <utils/Errors.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
-#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/IMemory.h>
 #include <utils/Log.h>
 
+#include <ui/DisplayInfo.h>
 #include <ui/ISurfaceComposer.h>
 #include <ui/ISurfaceFlingerClient.h>
 #include <ui/ISurface.h>
 #include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
-#include <ui/Point.h>
 
 #include <private/ui/SharedState.h>
 #include <private/ui/LayerState.h>
 #include <private/ui/SurfaceFlingerSynchro.h>
 
-#include <pixelflinger/pixelflinger.h>
-
-#include <binder/BpBinder.h>
-
 #define VERBOSE(...)	((void)0)
 //#define VERBOSE			LOGD
 
@@ -109,50 +103,8 @@
 
 // ---------------------------------------------------------------------------
 
-static void copyBlt(const GGLSurface& dst,
-        const GGLSurface& src, const Region& reg)
-{
-    Region::iterator iterator(reg);
-    if (iterator) {
-        // NOTE: dst and src must be the same format
-        Rect r;
-        const size_t bpp = bytesPerPixel(src.format);
-        const size_t dbpr = dst.stride * bpp;
-        const size_t sbpr = src.stride * bpp;
-        while (iterator.iterate(&r)) {
-            ssize_t h = r.bottom - r.top;
-            if (h) {
-                size_t size = (r.right - r.left) * bpp;
-                uint8_t* s = src.data + (r.left + src.stride * r.top) * bpp;
-                uint8_t* d = dst.data + (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);
-            }
-        }
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-surface_flinger_cblk_t::surface_flinger_cblk_t()
-{
-}
-
-// ---------------------------------------------------------------------------
-
-per_client_cblk_t::per_client_cblk_t()
-{
-}
-
 // these functions are used by the clients
-inline status_t per_client_cblk_t::validate(size_t i) const {
+status_t per_client_cblk_t::validate(size_t i) const {
     if (uint32_t(i) >= NUM_LAYERS_MAX)
         return BAD_INDEX;
     if (layers[i].swapState & eInvalidSurface)
@@ -248,8 +200,9 @@
         index = (state&eIndex) ^ ((state&eFlipRequested)>>1);
 
 	    // make sure this buffer is valid
-	    if (layer->surface[index].bits_offset < 0) {
-	        return status_t(layer->surface[index].bits_offset);
+        status_t err = layer->surface[index].status;
+	    if (err < 0) {
+	        return err;
 	    }
 
         if (inspect) {
@@ -273,7 +226,7 @@
 
 uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
 {
-    // atomically set eFlipRequested and clear eLocked and optionnaly
+    // atomically set eFlipRequested and clear eLocked and optionally
     // set eNextFlipPending if eFlipRequested was already set
 
     layer_cblk_t * const layer = layers + i;
@@ -290,7 +243,7 @@
 
         if (oldvalue & eFlipRequested)
             newvalue |= eNextFlipPending;
-            // if eFlipRequested was alread set, set eNextFlipPending
+            // if eFlipRequested was already set, set eNextFlipPending
 
     } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState)));
 
@@ -298,9 +251,9 @@
             int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift),
             int(newvalue));
 
-    // from this point, the server can kick in at anytime and use the first
+    // from this point, the server can kick in at any time and use the first
     // buffer, so we cannot use it anymore, and we must use the 'other'
-    // buffer instead (or wait if it is not availlable yet, see lock_layer).
+    // buffer instead (or wait if it is not available yet, see lock_layer).
 
     return newvalue;
 }
@@ -376,32 +329,6 @@
     return mStatus;
 }
 
-status_t SurfaceComposerClient::validateSurface(
-        per_client_cblk_t const* cblk, Surface const * surface)
-{
-    SurfaceID index = surface->ID();
-    if (cblk == 0) {
-        LOGE("cblk is null (surface id=%d, identity=%u)",
-                index, surface->getIdentity());
-        return NO_INIT;
-    }
-
-    status_t err = cblk->validate(index);
-    if (err != NO_ERROR) {
-        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
-                index, surface->getIdentity(), err, strerror(-err));
-        return err;
-    }
-
-    if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) {
-        LOGE("using an invalid surface id=%d, identity=%u should be %d",
-                index, surface->getIdentity(), cblk->layers[index].identity);
-        return NO_INIT;
-    }
-
-    return NO_ERROR;
-}
-
 sp<IBinder> SurfaceComposerClient::connection() const
 {
     return (mClient != 0) ? mClient->asBinder() : 0;
@@ -439,7 +366,6 @@
 
     sp<IMemory>                 controlMemory;
     sp<ISurfaceFlingerClient>   client;
-    sp<IMemoryHeap>             surfaceHeap;
 
     {
         Mutex::Autolock _lg(gLock);
@@ -462,9 +388,7 @@
         delete mPrebuiltLayerState;
         mPrebuiltLayerState = 0;
         controlMemory = mControlMemory;
-        surfaceHeap = mSurfaceHeap;
         mControlMemory.clear();
-        mSurfaceHeap.clear();
         mControl = 0;
         mStatus = NO_INIT;
     }
@@ -528,7 +452,13 @@
     return n;
 }
 
-sp<Surface> SurfaceComposerClient::createSurface(
+
+void SurfaceComposerClient::signalServer()
+{
+    mSignalServer->signal();
+}
+
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
         int pid,
         DisplayID display,
         uint32_t w,
@@ -536,14 +466,14 @@
         PixelFormat format,
         uint32_t flags)
 {
-    sp<Surface> result;
+    sp<SurfaceControl> result;
     if (mStatus == NO_ERROR) {
         ISurfaceFlingerClient::surface_data_t data;
         sp<ISurface> surface = mClient->createSurface(&data, pid,
                 display, w, h, format, flags);
         if (surface != 0) {
             if (uint32_t(data.token) < NUM_LAYERS_MAX) {
-                result = new Surface(this, surface, data, w, h, format, flags);
+                result = new SurfaceControl(this, surface, data, w, h, format, flags);
             }
         }
     }
@@ -568,186 +498,6 @@
     return err;
 }
 
-status_t SurfaceComposerClient::nextBuffer(Surface* surface,
-                        Surface::SurfaceInfo* info)
-{
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface);
-    if (err != NO_ERROR)
-        return err;
-
-    int32_t backIdx = surface->mBackbufferIndex;
-    layer_cblk_t* const lcblk = &(cblk->layers[index]);
-    const surface_info_t* const front = lcblk->surface + (1-backIdx);
-        info->w      = front->w;
-        info->h      = front->h;
-        info->format = front->format;
-        info->base   = surface->heapBase(1-backIdx);
-        info->bits   = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset);
-        info->bpr    = front->bpr;
-
-    return 0;
-}
-
-status_t SurfaceComposerClient::lockSurface(
-        Surface* surface,
-        Surface::SurfaceInfo* other,
-        Region* dirty,
-        bool blocking)
-{
-    Mutex::Autolock _l(surface->getLock());
-
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface);
-    if (err != NO_ERROR)
-        return err;
-
-    int32_t backIdx = cblk->lock_layer(size_t(index),
-            per_client_cblk_t::BLOCKING);
-    if (backIdx >= 0) {
-        surface->mBackbufferIndex = backIdx;
-        layer_cblk_t* const lcblk = &(cblk->layers[index]);
-        const surface_info_t* const back = lcblk->surface + backIdx;
-        const surface_info_t* const front = lcblk->surface + (1-backIdx);
-            other->w      = back->w;
-            other->h      = back->h;
-            other->format = back->format;
-            other->base   = surface->heapBase(backIdx);
-            other->bits   = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset);
-            other->bpr    = back->bpr;
-
-        const Rect bounds(other->w, other->h);
-        Region newDirtyRegion;
-
-        if (back->flags & surface_info_t::eBufferDirty) {
-            /* it is safe to write *back here, because we're guaranteed
-             * SurfaceFlinger is not touching it (since it just granted
-             * access to us) */
-            const_cast<surface_info_t*>(back)->flags &=
-                    ~surface_info_t::eBufferDirty;
-
-            // content is meaningless in this case and the whole surface
-            // needs to be redrawn.
-
-            newDirtyRegion.set(bounds);
-            if (dirty) {
-                *dirty = newDirtyRegion;
-            }
-
-            //if (bytesPerPixel(other->format) == 4) {
-            //    android_memset32(
-            //        (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr);
-            //} else {
-            //    android_memset16( // fill with green
-            //        (uint16_t*)other->bits, 0x7E0, other->h * other->bpr);
-            //}
-        }
-        else
-        {
-            if (dirty) {
-                dirty->andSelf(Region(bounds));
-                newDirtyRegion = *dirty;
-            } else {
-                newDirtyRegion.set(bounds);
-            }
-
-            Region copyback;
-            if (!(lcblk->flags & eNoCopyBack)) {
-                const Region previousDirtyRegion(surface->dirtyRegion());
-                copyback = previousDirtyRegion.subtract(newDirtyRegion);
-            }
-
-            if (!copyback.isEmpty()) {
-                // copy front to back
-                GGLSurface cb;
-                    cb.version = sizeof(GGLSurface);
-                    cb.width = back->w;
-                    cb.height = back->h;
-                    cb.stride = back->stride;
-                    cb.data = (GGLubyte*)surface->heapBase(backIdx);
-                    cb.data += back->bits_offset;
-                    cb.format = back->format;
-
-                GGLSurface t;
-                    t.version = sizeof(GGLSurface);
-                    t.width = front->w;
-                    t.height = front->h;
-                    t.stride = front->stride;
-                    t.data = (GGLubyte*)surface->heapBase(1-backIdx);
-                    t.data += front->bits_offset;
-                    t.format = front->format;
-
-                //const Region copyback(lcblk->region + 1-backIdx);
-                copyBlt(cb, t, copyback);
-            }
-        }
-
-        // update dirty region
-        surface->setDirtyRegion(newDirtyRegion);
-    }
-    return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR);
-}
-
-void SurfaceComposerClient::_signal_server()
-{
-    mSignalServer->signal();
-}
-
-void SurfaceComposerClient::_send_dirty_region(
-        layer_cblk_t* lcblk, const Region& dirty)
-{
-    const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
-    flat_region_t* flat_region = lcblk->region + index;
-    status_t err = dirty.write(flat_region, sizeof(flat_region_t));
-    if (err < NO_ERROR) {
-        // region doesn't fit, use the bounds
-        const Region reg(dirty.bounds());
-        reg.write(flat_region, sizeof(flat_region_t));
-    }
-}
-
-status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface)
-{
-    Mutex::Autolock _l(surface->getLock());
-
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface);
-    if (err != NO_ERROR)
-        return err;
-
-    Region dirty(surface->dirtyRegion());
-    const Rect& swapRect(surface->swapRectangle());
-    if (swapRect.isValid()) {
-        dirty.set(swapRect);
-    }
-
-    // transmit the dirty region
-    layer_cblk_t* const lcblk = &(cblk->layers[index]);
-    _send_dirty_region(lcblk, dirty);
-    uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
-    if (!(newstate & eNextFlipPending))
-        _signal_server();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::unlockSurface(Surface* surface)
-{
-    Mutex::Autolock _l(surface->getLock());
-
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface);
-    if (err != NO_ERROR)
-        return err;
-
-    layer_cblk_t* const lcblk = &(cblk->layers[index]);
-    cblk->unlock_layer(size_t(index));
-    return NO_ERROR;
-}
-
 void SurfaceComposerClient::openGlobalTransaction()
 {
     Mutex::Autolock _l(gLock);
@@ -866,14 +616,8 @@
     return NO_ERROR;
 }
 
-layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface)
+layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index)
 {
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface.get());
-    if (err != NO_ERROR)
-        return 0;
-
     // API usage error, do nothing.
     if (mTransactionOpen<=0) {
         LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d",
@@ -892,11 +636,11 @@
     return mStates.editArray() + i;
 }
 
-layer_state_t* SurfaceComposerClient::_lockLayerState(const sp<Surface>& surface)
+layer_state_t* SurfaceComposerClient::_lockLayerState(SurfaceID id)
 {
     layer_state_t* s;
     mLock.lock();
-    s = _get_state_l(surface);
+    s = _get_state_l(id);
     if (!s) mLock.unlock();
     return s;
 }
@@ -906,9 +650,9 @@
     mLock.unlock();
 }
 
-status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t y)
+status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::ePositionChanged;
     s->x = x;
@@ -917,9 +661,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h)
+status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eSizeChanged;
     s->w = w;
@@ -928,9 +672,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z)
+status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eLayerChanged;
     s->z = z;
@@ -938,32 +682,32 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::hide(Surface* surface)
+status_t SurfaceComposerClient::hide(SurfaceID id)
 {
-    return setFlags(surface, ISurfaceComposer::eLayerHidden,
+    return setFlags(id, ISurfaceComposer::eLayerHidden,
             ISurfaceComposer::eLayerHidden);
 }
 
-status_t SurfaceComposerClient::show(Surface* surface, int32_t)
+status_t SurfaceComposerClient::show(SurfaceID id, int32_t)
 {
-    return setFlags(surface, 0, ISurfaceComposer::eLayerHidden);
+    return setFlags(id, 0, ISurfaceComposer::eLayerHidden);
 }
 
-status_t SurfaceComposerClient::freeze(Surface* surface)
+status_t SurfaceComposerClient::freeze(SurfaceID id)
 {
-    return setFlags(surface, ISurfaceComposer::eLayerFrozen,
+    return setFlags(id, ISurfaceComposer::eLayerFrozen,
             ISurfaceComposer::eLayerFrozen);
 }
 
-status_t SurfaceComposerClient::unfreeze(Surface* surface)
+status_t SurfaceComposerClient::unfreeze(SurfaceID id)
 {
-    return setFlags(surface, 0, ISurfaceComposer::eLayerFrozen);
+    return setFlags(id, 0, ISurfaceComposer::eLayerFrozen);
 }
 
-status_t SurfaceComposerClient::setFlags(Surface* surface,
+status_t SurfaceComposerClient::setFlags(SurfaceID id,
         uint32_t flags, uint32_t mask)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eVisibilityChanged;
     s->flags &= ~mask;
@@ -973,11 +717,10 @@
     return NO_ERROR;
 }
 
-
 status_t SurfaceComposerClient::setTransparentRegionHint(
-        Surface* surface, const Region& transparentRegion)
+        SurfaceID id, const Region& transparentRegion)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eTransparentRegionChanged;
     s->transparentRegion = transparentRegion;
@@ -985,9 +728,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha)
+status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eAlphaChanged;
     s->alpha = alpha;
@@ -996,11 +739,11 @@
 }
 
 status_t SurfaceComposerClient::setMatrix(
-        Surface* surface,
+        SurfaceID id,
         float dsdx, float dtdx,
         float dsdy, float dtdy )
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eMatrixChanged;
     layer_state_t::matrix22_t matrix;
@@ -1013,9 +756,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::setFreezeTint(Surface* surface, uint32_t tint)
+status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eFreezeTintChanged;
     s->tint = tint;
diff --git a/libs/ui/SurfaceFlingerSynchro.cpp b/libs/ui/SurfaceFlingerSynchro.cpp
index 2e8fa12..c81db71 100644
--- a/libs/ui/SurfaceFlingerSynchro.cpp
+++ b/libs/ui/SurfaceFlingerSynchro.cpp
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlingerSynchro"
-
 #include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <binder/IPCThreadState.h>
-#include <utils/Log.h>
 
 #include <private/ui/SurfaceFlingerSynchro.h>
 
@@ -34,61 +22,10 @@
 
 // ---------------------------------------------------------------------------
 
-SurfaceFlingerSynchro::Barrier::Barrier()
-    : state(CLOSED) { 
-}
-
-SurfaceFlingerSynchro::Barrier::~Barrier() { 
-}
-
-void SurfaceFlingerSynchro::Barrier::open() {
-    asm volatile ("":::"memory");
-    Mutex::Autolock _l(lock);
-    state = OPENED;
-    cv.broadcast();
-}
-
-void SurfaceFlingerSynchro::Barrier::close() {
-    Mutex::Autolock _l(lock);
-    state = CLOSED;
-}
-
-void SurfaceFlingerSynchro::Barrier::waitAndClose() 
-{
-    Mutex::Autolock _l(lock);
-    while (state == CLOSED) {
-        // we're about to wait, flush the binder command buffer
-        IPCThreadState::self()->flushCommands();
-        cv.wait(lock);
-    }
-    state = CLOSED;
-}
-
-status_t SurfaceFlingerSynchro::Barrier::waitAndClose(nsecs_t timeout) 
-{
-    Mutex::Autolock _l(lock);
-    while (state == CLOSED) {
-        // we're about to wait, flush the binder command buffer
-        IPCThreadState::self()->flushCommands();
-        int err = cv.waitRelative(lock, timeout);
-        if (err != 0)
-            return err;
-    }
-    state = CLOSED;
-    return NO_ERROR;
-}
-
-// ---------------------------------------------------------------------------
-
 SurfaceFlingerSynchro::SurfaceFlingerSynchro(const sp<ISurfaceComposer>& flinger)
     : mSurfaceComposer(flinger)
 {
 }
-
-SurfaceFlingerSynchro::SurfaceFlingerSynchro()
-{
-}
-
 SurfaceFlingerSynchro::~SurfaceFlingerSynchro()
 {
 }
@@ -99,24 +36,6 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlingerSynchro::wait()
-{
-    mBarrier.waitAndClose();
-    return NO_ERROR;
-}
-
-status_t SurfaceFlingerSynchro::wait(nsecs_t timeout)
-{
-    if (timeout == 0)
-        return SurfaceFlingerSynchro::wait();
-    return mBarrier.waitAndClose(timeout);
-}
-
-void SurfaceFlingerSynchro::open()
-{
-    mBarrier.open();
-}
-
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
new file mode 100644
index 0000000..6cc4a5a
--- /dev/null
+++ b/libs/ui/tests/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	region.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+    libui
+
+LOCAL_MODULE:= test-region
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/libs/ui/tests/region.cpp b/libs/ui/tests/region.cpp
new file mode 100644
index 0000000..0deb2ba
--- /dev/null
+++ b/libs/ui/tests/region.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define LOG_TAG "Region"
+
+#include <stdio.h>
+#include <utils/Debug.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+using namespace android;
+
+int main()
+{
+    Region reg0( Rect(  0, 0,  100, 100 ) );
+    Region reg1 = reg0;
+    Region reg2, reg3;
+    
+    reg0.dump("reg0");
+    reg1.dump("reg1");
+
+    reg0 = reg0 | reg0.translate(150, 0);
+    reg0.dump("reg0");
+    reg1.dump("reg1");
+
+    reg0 = reg0 | reg0.translate(300, 0);
+    reg0.dump("reg0");
+    reg1.dump("reg1");
+
+    //reg2 = reg0 | reg0.translate(0, 100);
+    //reg0.dump("reg0");
+    //reg1.dump("reg1");
+    //reg2.dump("reg2");
+
+    //reg3 = reg0 | reg0.translate(0, 150);
+    //reg0.dump("reg0");
+    //reg1.dump("reg1");
+    //reg2.dump("reg2");
+    //reg3.dump("reg3");
+
+    LOGD("---");
+    reg2 = reg0 | reg0.translate(100, 0);
+    reg0.dump("reg0");
+    reg1.dump("reg1");
+    reg2.dump("reg2");
+    
+    return 0;
+}
+
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index a17e651..8ac697e 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -27,14 +27,18 @@
 #include <unistd.h>
 
 #include <string.h>
+
 #include <cutils/atomic.h>
+#include <cutils/properties.h>
+
+#include <utils/misc.h>
 
 #include <android_runtime/ActivityManager.h>
+
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryBase.h>
-#include <cutils/properties.h>
 
 #include <media/MediaPlayerInterface.h>
 #include <media/mediarecorder.h>
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 25cfcb8..335b0b0 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -131,6 +131,18 @@
 /* Interfaces defined by EGL_KHR_image above */
 #endif
 
+
+#ifndef EGL_ANDROID_swap_rectangle
+#define EGL_ANDROID_swap_rectangle 1
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSetSwapRectangleANDROID (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSWAPRECTANGLEANDROIDPROC) (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height);
+#endif
+
+
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h
index ac00901..9561490 100644
--- a/opengl/include/EGL/eglplatform.h
+++ b/opengl/include/EGL/eglplatform.h
@@ -89,12 +89,19 @@
 
 #elif defined(ANDROID)
 
-#include <EGL/eglnatives.h>
+struct android_native_window_t;
+struct egl_native_pixmap_t;
 
-typedef struct egl_native_window_t*     EGLNativeWindowType;
+typedef struct android_native_window_t* EGLNativeWindowType;
 typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
 typedef void*                           EGLNativeDisplayType;
 
+#ifndef EGL_ANDROID_image_native_buffer
+#define EGL_ANDROID_image_native_buffer 1
+struct android_native_buffer_t;
+#define EGL_NATIVE_BUFFER_ANDROID       0x6000  /* eglCreateImageKHR target */
+#endif
+
 #else
 #error "Platform not recognized"
 #endif
diff --git a/opengl/include/GLES/glplatform.h b/opengl/include/GLES/glplatform.h
index 0924cae..198e679 100644
--- a/opengl/include/GLES/glplatform.h
+++ b/opengl/include/GLES/glplatform.h
@@ -28,12 +28,6 @@
 
 #define GL_APIENTRY KHRONOS_APIENTRY
 
-// XXX: this should probably not be here
-#define GL_DIRECT_TEXTURE_2D_QUALCOMM               0x7E80
-
-// XXX: not sure how this is intended to be used
-#define GL_GLEXT_PROTOTYPES
-
 #endif
 
 #endif /* __glplatform_h_ */
diff --git a/opengl/include/GLES2/gl2.h b/opengl/include/GLES2/gl2.h
new file mode 100644
index 0000000..0182a67
--- /dev/null
+++ b/opengl/include/GLES2/gl2.h
@@ -0,0 +1,620 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void             GLvoid;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0                 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+
+/* Boolean */
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+
+/* BeginMode */
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT            0x8192
+
+/* DataType */
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                  0x8B30
+#define GL_VERTEX_SHADER                    0x8B31
+#define GL_MAX_VERTEX_ATTRIBS               0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#define GL_MAX_VARYING_VECTORS              0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS   0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS          0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
+#define GL_SHADER_TYPE                      0x8B4F
+#define GL_DELETE_STATUS                    0x8B80
+#define GL_LINK_STATUS                      0x8B82
+#define GL_VALIDATE_STATUS                  0x8B83
+#define GL_ATTACHED_SHADERS                 0x8B85
+#define GL_ACTIVE_UNIFORMS                  0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH        0x8B87
+#define GL_ACTIVE_ATTRIBUTES                0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH      0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION         0x8B8C
+#define GL_CURRENT_PROGRAM                  0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+
+/* StringName */
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                        0x1702
+
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED        0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE           0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE         0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE           0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED     0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER        0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_STENCIL_INDEX8                 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+
+#define GL_NONE                           0
+
+#define GL_FRAMEBUFFER_COMPLETE                      0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                   0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void         GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const char* name);
+GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
+GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void         GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void         GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void* indices);
+GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glFinish (void);
+GL_APICALL void         GL_APIENTRY glFlush (void);
+GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLuint program, const char* name);
+GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum       GL_APIENTRY glGetError (void);
+GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void         GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL int          GL_APIENTRY glGetUniformLocation (GLuint program, const char* name);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer);
+GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void         GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const char** string, const GLint* length);
+GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
new file mode 100644
index 0000000..72f1ae7
--- /dev/null
+++ b/opengl/include/GLES2/gl2ext.h
@@ -0,0 +1,518 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 8271 $ on $Date:: 2009-05-21 09:33:40 -0700 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+#   define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES                                        0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES                                    0x8B90
+#define GL_PALETTE4_RGBA8_OES                                   0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES                                0x8B92
+#define GL_PALETTE4_RGBA4_OES                                   0x8B93
+#define GL_PALETTE4_RGB5_A1_OES                                 0x8B94
+#define GL_PALETTE8_RGB8_OES                                    0x8B95
+#define GL_PALETTE8_RGBA8_OES                                   0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES                                0x8B97
+#define GL_PALETTE8_RGBA4_OES                                   0x8B98
+#define GL_PALETTE8_RGB5_A1_OES                                 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES                                0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES                                0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_LENGTH_OES                            0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES                       0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES                           0x87FF
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_WRITE_ONLY_OES                                       0x88B9
+#define GL_BUFFER_ACCESS_OES                                    0x88BB
+#define GL_BUFFER_MAPPED_OES                                    0x88BC
+#define GL_BUFFER_MAP_POINTER_OES                               0x88BD
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_DEPTH_STENCIL_OES                                    0x84F9
+#define GL_UNSIGNED_INT_24_8_OES                                0x84FA
+#define GL_DEPTH24_STENCIL8_OES                                 0x88F0
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_RGB8_OES                                             0x8051
+#define GL_RGBA8_OES                                            0x8058
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES                  0x8B8B
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_STENCIL_INDEX1_OES                                   0x8D46
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_STENCIL_INDEX4_OES                                   0x8D47
+#endif
+
+/* GL_OES_texture3D */
+#ifndef GL_OES_texture3D
+#define GL_TEXTURE_WRAP_R_OES                                   0x8072
+#define GL_TEXTURE_3D_OES                                       0x806F
+#define GL_TEXTURE_BINDING_3D_OES                               0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES                              0x8073
+#define GL_SAMPLER_3D_OES                                       0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES        0x8CD4
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES                                       0x8D61
+#endif
+
+/* GL_OES_vertex_half_float */
+/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_UNSIGNED_INT_10_10_10_2_OES                          0x8DF6
+#define GL_INT_10_10_10_2_OES                                   0x8DF7
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_3DC_X_AMD                                            0x87F9
+#define GL_3DC_XY_AMD                                           0x87FA
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_ATC_RGB_AMD                                          0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      0x87EE
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD                                      0x8740
+#endif
+
+/* GL_AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD                                     0x8BC0
+#define GL_COUNTER_RANGE_AMD                                    0x8BC1
+#define GL_UNSIGNED_INT64_AMD                                   0x8BC2
+#define GL_PERCENTAGE_AMD                                       0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD                         0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD                              0x8BC5
+#define GL_PERFMON_RESULT_AMD                                   0x8BC6
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT                           0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       0x84FF
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT                      0x8368
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA                                                 0x80E1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA                                                 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV                           0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV                           0x8366
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV                                     0x84F2
+#define GL_FENCE_STATUS_NV                                      0x84F3
+#define GL_FENCE_CONDITION_NV                                   0x84F4
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM                             0x8FA0
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*
+ * OES extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#endif
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#endif
+
+/* GL_OES_depth_texture */
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif
+
+/* GL_OES_fbo_render_mipmap */
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif
+
+/* GL_OES_fragment_precision_high */
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void** params);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void** params);
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif
+
+/* GL_OES_vertex_half_float */
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
+/* AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, char *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, char *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/opengl/include/GLES2/gl2platform.h b/opengl/include/GLES2/gl2platform.h
new file mode 100644
index 0000000..3e9036c
--- /dev/null
+++ b/opengl/include/GLES2/gl2platform.h
@@ -0,0 +1,29 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X  gl2.h
+ * Last modified on 2008/12/19
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL  KHRONOS_APICALL
+#endif
+
+#define GL_APIENTRY KHRONOS_APIENTRY
+
+#endif /* __gl2platform_h_ */
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 3ce0414..d1ed82e 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -6,6 +6,9 @@
 
 include $(CLEAR_VARS)
 
+# Set to 1 to use gralloc and copybits
+LIBAGL_USE_GRALLOC_COPYBITS := 1
+
 LOCAL_SRC_FILES:= \
 	egl.cpp                     \
 	state.cpp		            \
@@ -29,13 +32,24 @@
 
 ifneq ($(TARGET_SIMULATOR),true)
     # we need to access the private Bionic header <bionic_tls.h>
-    LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
+    LOCAL_C_INCLUDES += bionic/libc/private
 endif
 
-LOCAL_SHARED_LIBRARIES := libcutils libutils libpixelflinger
+ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1)
+    LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS
+    LOCAL_SRC_FILES += copybit.cpp
+    LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc
+endif
+
+LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
 LOCAL_CFLAGS += -fvisibility=hidden
 
 LOCAL_LDLIBS := -lpthread -ldl
-LOCAL_MODULE:= libagl
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
+LOCAL_MODULE:= libGLES_android
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp
index ce31854..9deb2cf 100644
--- a/opengl/libagl/TextureObjectManager.cpp
+++ b/opengl/libagl/TextureObjectManager.cpp
@@ -1,16 +1,16 @@
 /*
  ** 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.
  */
 
@@ -19,11 +19,13 @@
 #include "context.h"
 #include "TextureObjectManager.h"
 
+#include <private/ui/android_natives_priv.h>
+
 namespace android {
 // ----------------------------------------------------------------------------
 
 EGLTextureObject::EGLTextureObject()
-    : mCount(0), mSize(0)
+    : mSize(0)
 {
     init();
 }
@@ -53,6 +55,10 @@
     memset(crop_rect, 0, sizeof(crop_rect));
     generate_mipmap = GL_FALSE;
     direct = GL_FALSE;
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    copybits_fd = -1;
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+    buffer = 0;
 }
 
 void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old)
@@ -123,6 +129,7 @@
     }
     surface = *s;
     internalformat = 0;
+    buffer = 0;
 
     // we should keep the crop_rect, but it's delicate because
     // the new size of the surface could make it invalid.
@@ -141,12 +148,26 @@
     return NO_ERROR;
 }
 
+status_t EGLTextureObject::setImage(android_native_buffer_t* native_buffer)
+{
+    GGLSurface sur;
+    sur.version = sizeof(GGLSurface);
+    sur.width = native_buffer->width;
+    sur.height= native_buffer->height;
+    sur.stride= native_buffer->stride;
+    sur.format= native_buffer->format;
+    sur.data  = 0;
+    setSurface(&sur);
+    buffer = native_buffer;
+    return NO_ERROR;
+}
+
 status_t EGLTextureObject::reallocate(
         GLint level, int w, int h, int s,
         int format, int compressedFormat, int bpr)
 {
     const size_t size = h * bpr;
-    if (level == 0) 
+    if (level == 0)
     {
         if (size!=mSize || !surface.data) {
             if (mSize && surface.data) {
@@ -177,9 +198,9 @@
                 return NO_MEMORY;
         }
 
-        LOGW_IF(level-1 >= mNumExtraLod, 
+        LOGW_IF(level-1 >= mNumExtraLod,
                 "specifying mipmap level %d, but # of level is %d",
-                level, mNumExtraLod+1);        
+                level, mNumExtraLod+1);
 
         GGLSurface& mipmap = editMip(level);
         if (mipmap.data)
@@ -224,7 +245,7 @@
 // ----------------------------------------------------------------------------
 
 EGLSurfaceManager::EGLSurfaceManager()
-    : TokenManager(), mCount(0)
+    : TokenManager()
 {
 }
 
diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h
index 74ed1a4..e0eadf1 100644
--- a/opengl/libagl/TextureObjectManager.h
+++ b/opengl/libagl/TextureObjectManager.h
@@ -1,16 +1,16 @@
 /*
 ** 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.
 */
 
@@ -30,6 +30,7 @@
 #include <private/pixelflinger/ggl_context.h>
 
 #include <GLES/gl.h>
+#include <EGL/egl.h>
 
 #include "Tokenizer.h"
 #include "TokenManager.h"
@@ -39,22 +40,20 @@
 
 // ----------------------------------------------------------------------------
 
-class EGLTextureObject
+class EGLTextureObject : public LightRefBase<EGLTextureObject>
 {
 public:
                     EGLTextureObject();
                    ~EGLTextureObject();
 
-    // protocol for sp<>
-    inline  void        incStrong(const void* id) const;
-    inline  void        decStrong(const void* id) const;
-    inline  uint32_t    getStrongCount() const;
+    status_t    setSurface(GGLSurface const* s);
+    status_t    setImage(android_native_buffer_t* buffer);
+    void        setImageBits(void* vaddr) { surface.data = (GGLubyte*)vaddr; }
 
-    status_t            setSurface(GGLSurface const* s);
     status_t            reallocate(GLint level,
                             int w, int h, int s,
                             int format, int compressedFormat, int bpr);
-    inline  size_t      size() const;
+    inline  size_t      size() const { return mSize; }
     const GGLSurface&   mip(int lod) const;
     GGLSurface&         editMip(int lod);
     bool                hasMipmaps() const { return mMipmaps!=0; }
@@ -65,7 +64,6 @@
         status_t        allocateMipmaps();
             void        freeMipmaps();
             void        init();
-    mutable int32_t     mCount;
     size_t              mSize;
     GGLSurface          *mMipmaps;
     int                 mNumExtraLod;
@@ -81,36 +79,22 @@
     GLint               crop_rect[4];
     GLint               generate_mipmap;
     GLint               direct;
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    int                 copybits_fd;
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+    android_native_buffer_t* buffer;
 };
 
-void EGLTextureObject::incStrong(const void* id) const {
-    android_atomic_inc(&mCount);
-}
-void EGLTextureObject::decStrong(const void* id) const {
-    if (android_atomic_dec(&mCount) == 1) {
-        delete this;
-    }
-}
-uint32_t EGLTextureObject::getStrongCount() const {
-    return mCount;
-}
-size_t EGLTextureObject::size() const {
-    return mSize;
-}
-
 // ----------------------------------------------------------------------------
 
-class EGLSurfaceManager : public TokenManager
+class EGLSurfaceManager :
+    public LightRefBase<EGLSurfaceManager>,
+    public TokenManager
 {
 public:
                 EGLSurfaceManager();
                 ~EGLSurfaceManager();
 
-    // protocol for sp<>
-    inline  void    incStrong(const void* id) const;
-    inline  void    decStrong(const void* id) const;
-    typedef void    weakref_type;
-
     sp<EGLTextureObject>    createTexture(GLuint name);
     sp<EGLTextureObject>    removeTexture(GLuint name);
     sp<EGLTextureObject>    replaceTexture(GLuint name);
@@ -118,21 +102,10 @@
     sp<EGLTextureObject>    texture(GLuint name);
 
 private:
-    mutable int32_t                             mCount;
     mutable Mutex                               mLock;
     KeyedVector< GLuint, sp<EGLTextureObject> > mTextures;
 };
 
-void EGLSurfaceManager::incStrong(const void* id) const {
-    android_atomic_inc(&mCount);
-}
-void EGLSurfaceManager::decStrong(const void* id) const {
-    if (android_atomic_dec(&mCount) == 1) {
-        delete this;
-    }
-}
-
-
 // ----------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp
index 3e9c6a5..cffe880 100644
--- a/opengl/libagl/array.cpp
+++ b/opengl/libagl/array.cpp
@@ -1,16 +1,16 @@
-/* 
+/*
 ** 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.
 */
 
@@ -26,6 +26,9 @@
 #include "primitives.h"
 #include "texture.h"
 #include "BufferObjectManager.h"
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include "copybit.h"
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
 
 // ----------------------------------------------------------------------------
 
@@ -250,7 +253,7 @@
     v[2] = GGL_S_TO_X(p[2]);
 }
 
-typedef array_t::fetcher_t fn_t; 
+typedef array_t::fetcher_t fn_t;
 
 static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x}
     { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0,
@@ -334,7 +337,7 @@
     this->bounds = count;
 }
 
-inline void array_t::resolve() 
+inline void array_t::resolve()
 {
     physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer;
 }
@@ -465,7 +468,7 @@
         // We compute directly the index of a "free" entry from the locked
         // state of v[2] and v[3].
         v = c->vc.vBuffer + 2;
-        v += v[0].locked | (v[1].locked<<1);       
+        v += v[0].locked | (v[1].locked<<1);
     }
     // note: compileElement clears v->flags
     c->arrays.compileElement(c, v, index);
@@ -480,7 +483,7 @@
 
 #if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED
 
-    vertex_t* const v = c->vc.vCache + 
+    vertex_t* const v = c->vc.vCache +
             (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1));
 
     if (ggl_likely(v->index == index)) {
@@ -491,7 +494,7 @@
 
 #elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU
 
-    vertex_t* v = c->vc.vCache + 
+    vertex_t* v = c->vc.vCache +
             (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2;
 
     // always record LRU in v[0]
@@ -532,12 +535,12 @@
         return;
 
     // vertex cache size must be multiple of 1
-    const GLsizei vcs = 
+    const GLsizei vcs =
             (vertex_cache_t::VERTEX_BUFFER_SIZE +
              vertex_cache_t::VERTEX_CACHE_SIZE);
     do {
         vertex_t* v = c->vc.vBuffer;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.cull = vertex_t::CLIP_ALL;
         c->arrays.compileElements(c, v, first, num);
         first += num;
@@ -569,13 +572,13 @@
     count -= 1;
 
     // vertex cache size must be multiple of 1
-    const GLsizei vcs = 
+    const GLsizei vcs =
         (vertex_cache_t::VERTEX_BUFFER_SIZE +
          vertex_cache_t::VERTEX_CACHE_SIZE - 1);
     do {
-        v0 = c->vc.vBuffer + 0; 
+        v0 = c->vc.vBuffer + 0;
         v  = c->vc.vBuffer + 1;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.compileElements(c, v, first, num);
         first += num;
         count -= num;
@@ -602,7 +605,7 @@
         return;
     drawPrimitivesLineStrip(c, first, count);
     if (ggl_likely(count >= 3)) {
-        vertex_t* v0 = c->vc.vBuffer; 
+        vertex_t* v0 = c->vc.vBuffer;
         vertex_t* v1 = c->vc.vBuffer + 1;
         c->arrays.compileElement(c, v1, first);
         const uint32_t cc = v0->flags & v1->flags;
@@ -617,12 +620,12 @@
         return;
 
     // vertex cache size must be multiple of 2
-    const GLsizei vcs = 
+    const GLsizei vcs =
         ((vertex_cache_t::VERTEX_BUFFER_SIZE +
         vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2;
     do {
         vertex_t* v = c->vc.vBuffer;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.cull = vertex_t::CLIP_ALL;
         c->arrays.compileElements(c, v, first, num);
         first += num;
@@ -662,14 +665,14 @@
     // because it allows us to preserve the same winding when the whole
     // batch is culled. We also need 2 extra vertices in the array, because
     // we always keep the two first ones.
-    const GLsizei vcs = 
+    const GLsizei vcs =
         ((vertex_cache_t::VERTEX_BUFFER_SIZE +
           vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2;
     do {
-        v0 = c->vc.vBuffer + 0; 
-        v1 = c->vc.vBuffer + 1; 
+        v0 = c->vc.vBuffer + 0;
+        v1 = c->vc.vBuffer + 1;
         v  = c->vc.vBuffer + 2;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.compileElements(c, v, first, num);
         first += num;
         count -= num;
@@ -697,13 +700,19 @@
     } while (count > 0);
 }
 
-void drawPrimitivesTriangleStrip(ogles_context_t* c, 
+void drawPrimitivesTriangleStrip(ogles_context_t* c,
         GLint first, GLsizei count) {
     drawPrimitivesTriangleFanOrStrip(c, first, count, 1);
 }
 
 void drawPrimitivesTriangleFan(ogles_context_t* c,
         GLint first, GLsizei count) {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    if (drawTrangleFanWithCopybit(c, first, count)) {
+        return;
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
     drawPrimitivesTriangleFanOrStrip(c, first, count, 2);
 }
 
@@ -713,12 +722,12 @@
         return;
 
     // vertex cache size must be multiple of 3
-    const GLsizei vcs = 
+    const GLsizei vcs =
         ((vertex_cache_t::VERTEX_BUFFER_SIZE +
         vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3;
     do {
         vertex_t* v = c->vc.vBuffer;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.cull = vertex_t::CLIP_ALL;
         c->arrays.compileElements(c, v, first, num);
         first += num;
@@ -779,11 +788,11 @@
 {
     if (ggl_unlikely(count < 2))
         return;
-    
+
     vertex_t * const v = c->vc.vBuffer;
     vertex_t* v0 = v;
     vertex_t* v1;
-    
+
     const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
     c->arrays.compileElement(c, v0, read_index(type, indices));
     count -= 1;
@@ -806,11 +815,11 @@
         drawIndexedPrimitivesLines(c, count, indices);
         return;
     }
- 
+
     vertex_t * const v = c->vc.vBuffer;
     vertex_t* v0 = v;
     vertex_t* v1;
-    
+
     const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
     c->arrays.compileElement(c, v0, read_index(type, indices));
     count -= 1;
@@ -825,7 +834,7 @@
     } while (count);
     v1->locked = 0;
 
-    v1 = c->vc.vBuffer; 
+    v1 = c->vc.vBuffer;
     const uint32_t cc = v0->flags & v1->flags;
     if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
         c->prims.renderLine(c, v0, v1);
@@ -861,7 +870,7 @@
 
     if (ggl_unlikely(count < 3))
         return;
-    
+
     vertex_t * const v = c->vc.vBuffer;
     vertex_t* v0 = v;
     vertex_t* v1 = v+1;
@@ -985,17 +994,17 @@
     const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first);
     const size_t stride = c->arrays.vertex.stride / 4;
 //    const GLfixed* const& m = c->transforms.mvp.matrix.m;
-    
+
     GLfixed m[16];
     memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m));
-    
+
     do {
         const GLfixed rx = vp[0];
         const GLfixed ry = vp[1];
         const GLfixed rz = vp[2];
         vp += stride;
         v->index = first++;
-        v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); 
+        v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]);
         v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
         v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
         v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]);
@@ -1023,7 +1032,7 @@
 #pragma mark clippers
 #endif
 
-static void clipVec4(vec4_t& nv, 
+static void clipVec4(vec4_t& nv,
         GLfixed t, const vec4_t& s, const vec4_t& p)
 {
     for (int i=0; i<4 ; i++)
@@ -1086,10 +1095,10 @@
     // automatically turn it off (in fact we could when the 4th coordinate
     // is not spcified in the vertex array).
     // W interpolation is never needed for points.
-    GLboolean perspective = 
+    GLboolean perspective =
         c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS);
     c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective);
-    
+
     // set anti-aliasing
     GLboolean smooth = GL_FALSE;
     switch (mode) {
@@ -1120,7 +1129,7 @@
     if (enables & GGL_ENABLE_TMUS) { // needs texture transforms
         want |= transform_state_t::TEXTURE;
     }
-    if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { 
+    if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) {
         want |= transform_state_t::MODELVIEW; // needs eye coords
     }
     ogles_validate_transform(c, want);
@@ -1139,18 +1148,18 @@
 
     c->arrays.mv_transform =
         c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2];
-    
+
     /*
      * ***********************************************************************
      *  pick fetchers
      * ***********************************************************************
      */
-    
+
     array_machine_t& am = c->arrays;
     am.vertex.fetch = fetchNop;
     am.normal.fetch = currentNormal;
     am.color.fetch = currentColor;
-    
+
     if (am.vertex.enable) {
         am.vertex.resolve();
         if (am.vertex.bo || am.vertex.pointer) {
@@ -1366,9 +1375,18 @@
     if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK))
         return; // all triangles are culled
 
+
     validate_arrays(c, mode);
+
+    const uint32_t enables = c->rasterizer.state.enables;
+    if (enables & GGL_ENABLE_TMUS)
+        ogles_lock_textures(c);
+
     drawArraysPrims[mode](c, first, count);
 
+    if (enables & GGL_ENABLE_TMUS)
+        ogles_unlock_textures(c);
+
 #if VC_CACHE_STATISTICS
     c->vc.total = count;
     c->vc.dump_stats(mode);
@@ -1413,15 +1431,23 @@
     // clear the vertex-cache
     c->vc.clear();
     validate_arrays(c, mode);
-    
+
     // if indices are in a buffer object, the pointer is treated as an
     // offset in that buffer.
     if (c->arrays.element_array_buffer) {
         indices = c->arrays.element_array_buffer->data + uintptr_t(indices);
     }
 
-    drawElementsPrims[mode](c, count, indices);
+    const uint32_t enables = c->rasterizer.state.enables;
+    if (enables & GGL_ENABLE_TMUS)
+        ogles_lock_textures(c);
 
+    drawElementsPrims[mode](c, count, indices);
+    
+    if (enables & GGL_ENABLE_TMUS)
+        ogles_unlock_textures(c);
+
+    
 #if VC_CACHE_STATISTICS
     c->vc.total = count;
     c->vc.dump_stats(mode);
@@ -1448,7 +1474,7 @@
             return;
         }
     }
-    ((target == GL_ARRAY_BUFFER) ? 
+    ((target == GL_ARRAY_BUFFER) ?
             c->arrays.array_buffer : c->arrays.element_array_buffer) = bo;
 }
 
@@ -1467,7 +1493,7 @@
         ogles_error(c, GL_INVALID_ENUM);
         return;
     }
-    buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? 
+    buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
             c->arrays.array_buffer : c->arrays.element_array_buffer);
 
     if (bo == 0) {
@@ -1497,7 +1523,7 @@
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
-    buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? 
+    buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
             c->arrays.array_buffer : c->arrays.element_array_buffer);
 
     if (bo == 0) {
@@ -1545,7 +1571,7 @@
                 }
             }
         }
-    }    
+    }
     c->bufferObjectManager->deleteBuffers(n, buffers);
     c->bufferObjectManager->recycleTokens(n, buffers);
 }
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
new file mode 100644
index 0000000..427e42a
--- /dev/null
+++ b/opengl/libagl/copybit.cpp
@@ -0,0 +1,370 @@
+/*
+**
+** 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 <stdlib.h>
+#include <stdio.h>
+
+#include "context.h"
+#include "fp.h"
+#include "state.h"
+#include "matrix.h"
+#include "vertex.h"
+#include "light.h"
+#include "primitives.h"
+#include "texture.h"
+#include "BufferObjectManager.h"
+
+#include "TextureObjectManager.h"
+#include <hardware/gralloc.h>
+#include <hardware/copybit.h>
+#include "gralloc_priv.h"
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static void textureToCopyBitImage(const GGLSurface* surface, int fd, copybit_image_t* img) {
+    img->w      = surface->stride;
+    img->h      = surface->height;
+    img->format = surface->format;
+    img->offset = 0;
+    img->base   = surface->data;
+    img->fd     = fd;
+}
+
+struct clipRectRegion : public copybit_region_t {
+    clipRectRegion(ogles_context_t* c) {
+        next = iterate;
+        int x = c->viewport.scissor.x;
+        int y = c->viewport.scissor.y;
+        r.l = x;
+        r.t = y;
+        r.r = x + c->viewport.scissor.w;
+        r.b = y + c->viewport.scissor.h;
+        firstTime = true;
+    }
+private:
+    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+        clipRectRegion* myself = (clipRectRegion*) self;
+        if (myself->firstTime) {
+            myself->firstTime = false;
+            *rect = myself->r;
+            return 1;
+        }
+        return 0;
+    }
+    mutable copybit_rect_t r;
+    mutable bool firstTime;
+};
+
+static bool supportedCopybitsFormat(int format) {
+    switch (format) {
+    case COPYBIT_FORMAT_RGBA_8888:
+    case COPYBIT_FORMAT_RGB_565:
+    case COPYBIT_FORMAT_BGRA_8888:
+    case COPYBIT_FORMAT_RGBA_5551:
+    case COPYBIT_FORMAT_RGBA_4444:
+    case COPYBIT_FORMAT_YCbCr_422_SP:
+    case COPYBIT_FORMAT_YCbCr_420_SP:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static bool hasAlpha(int format) {
+    switch (format) {
+    case COPYBIT_FORMAT_RGBA_8888:
+    case COPYBIT_FORMAT_BGRA_8888:
+    case COPYBIT_FORMAT_RGBA_5551:
+    case COPYBIT_FORMAT_RGBA_4444:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static inline int fixedToByte(GGLfixed val) {
+    return (val - (val >> 8)) >> 8;
+}
+
+/**
+ * Performs a quick check of the rendering state. If this function returns
+ * false we cannot use the copybit driver.
+ */
+
+static bool checkContext(ogles_context_t* c) {
+
+	// By convenction copybitQuickCheckContext() has already returned true.
+	// avoid checking the same information again.
+	
+    if (c->copybits.blitEngine == NULL
+            || (c->rasterizer.state.enables
+                    & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) != 0) {
+        return false;
+    }
+
+    // Note: The drawSurfaceFd is only set for destination
+    // surfaces types that are supported by the hardware and
+    // do not have an alpha channel. So we don't have to re-check that here.
+
+    static const int tmu = 0;
+    texture_unit_t& u(c->textures.tmu[tmu]);
+    EGLTextureObject* textureObject = u.texture;
+
+    if (!supportedCopybitsFormat(textureObject->surface.format)) {
+        return false;
+    }
+    return true;
+}
+
+
+static bool copybit(GLint x, GLint y,
+        GLint w, GLint h,
+        EGLTextureObject* textureObject,
+        const GLint* crop_rect,
+        int transform,
+        ogles_context_t* c)
+{
+    // We assume checkContext has already been called and has already
+    // returned true.
+
+    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
+
+    y = cbSurface.height - (y + h);
+
+    const GLint Ucr = crop_rect[0];
+    const GLint Vcr = crop_rect[1];
+    const GLint Wcr = crop_rect[2];
+    const GLint Hcr = crop_rect[3];
+
+    int32_t dsdx = (Wcr << 16) / w;   // dsdx =  ((Wcr/w)/Wt)*Wt
+    int32_t dtdy = ((-Hcr) <<  16) / h;   // dtdy = -((Hcr/h)/Ht)*Ht
+
+    if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale
+            || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) {
+        // The requested scale is out of the range the hardware
+        // can support.
+        return false;
+    }
+
+    int32_t texelArea = gglMulx(dtdy, dsdx);
+    if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) {
+        // Non-linear filtering on a texture enlargement.
+        return false;
+    }
+
+    if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) {
+        // Non-linear filtering on an texture shrink.
+        return false;
+    }
+
+    const uint32_t enables = c->rasterizer.state.enables;
+    int planeAlpha = 255;
+    static const int tmu = 0;
+    texture_t& tev(c->rasterizer.state.texture[tmu]);
+    bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format);
+    switch (tev.env) {
+
+    case GGL_REPLACE:
+        if (!srcTextureHasAlpha) {
+            planeAlpha = fixedToByte(c->currentColorClamped.a);
+        }
+        break;
+
+    case GGL_MODULATE:
+        if (! (c->currentColorClamped.r == FIXED_ONE
+                && c->currentColorClamped.g == FIXED_ONE
+                && c->currentColorClamped.b == FIXED_ONE)) {
+            return false;
+        }
+        planeAlpha = fixedToByte(c->currentColorClamped.a);
+        break;
+
+    default:
+        // Incompatible texture environment.
+        return false;
+    }
+
+    bool blending = false;
+
+    if ((enables & GGL_ENABLE_BLENDING)
+            && !(c->rasterizer.state.blend.src == GL_ONE
+                    && c->rasterizer.state.blend.dst == GL_ZERO)) {
+        // Blending is OK if it is
+        // the exact kind of blending that the copybits hardware supports.
+        // Note: The hardware only supports
+        // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA,
+        // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA.
+        // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case,
+        // because the performance is worth it, even if the results are
+        // not correct.
+        if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA
+                || c->rasterizer.state.blend.src == GL_ONE)
+                && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA
+                && c->rasterizer.state.blend.alpha_separate == 0)) {
+            // Incompatible blend mode.
+            return false;
+        }
+        blending = true;
+    } else {
+        // No blending is OK if we are not using alpha.
+        if (srcTextureHasAlpha || planeAlpha != 255) {
+            // Incompatible alpha
+            return false;
+        }
+    }
+
+    if (srcTextureHasAlpha && planeAlpha != 255) {
+        // Can't do two types of alpha at once.
+        return false;
+    }
+
+    // LOGW("calling copybits");
+
+    copybit_device_t* copybit = c->copybits.blitEngine;
+    copybit_image_t dst;
+    textureToCopyBitImage(&cbSurface, c->copybits.drawSurfaceFd, &dst);
+    copybit_rect_t drect = {x, y, x+w, y+h};
+
+    copybit_image_t src;
+    textureToCopyBitImage(&textureObject->surface, textureObject->copybits_fd,
+            &src);
+    copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
+
+    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
+    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
+
+    copybit->set_parameter(copybit, COPYBIT_DITHER,
+            (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
+
+    clipRectRegion it(c);
+    copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+    return true;
+}
+
+/*
+ * Try to draw a triangle fan with copybit, return false if we fail.
+ */
+bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) {
+    if (! checkContext(c)) {
+        return false;
+    }
+
+    c->arrays.compileElements(c, c->vc.vBuffer, 0, 4);
+    // Is the result a screen aligned rectangle?
+    int sx[4];
+    int sy[4];
+    for (int i = 0; i < 4; i++) {
+        GLfixed x = c->vc.vBuffer[i].window.x;
+        GLfixed y = c->vc.vBuffer[i].window.y;
+        if (x < 0 || y < 0 || (x & 0xf) != 0 || (y & 0xf) != 0) {
+            return false;
+        }
+        sx[i] = x >> 4;
+        sy[i] = y >> 4;
+    }
+
+    /*
+     * This is the pattern we're looking for:
+     *    (2)--(3)
+     *     |\   |
+     *     | \  |
+     *     |  \ |
+     *     |   \|
+     *    (1)--(0)
+     *
+     */
+    int dx[4];
+    int dy[4];
+    for (int i = 0; i < 4; i++) {
+        int i1 = (i + 1) & 3;
+        dx[i] = sx[i] - sx[i1];
+        dy[i] = sy[i] - sy[i1];
+    }
+    if (dx[1] | dx[3] | dy[0] | dy[2]) {
+        return false;
+    }
+    if (dx[0] != -dx[2] || dy[1] != -dy[3]) {
+        return false;
+    }
+
+    int x = sx[1];
+    int y = sy[1];
+    int w = dx[0];
+    int h = dy[3];
+
+    // We expect the texture coordinates to always be the unit square:
+
+    static const GLfixed kExpectedUV[8] = {
+        0, 0,
+        0, FIXED_ONE,
+        FIXED_ONE, FIXED_ONE,
+        FIXED_ONE, 0
+    };
+    {
+        const GLfixed* pExpected = &kExpectedUV[0];
+        for (int i = 0; i < 4; i++) {
+            GLfixed u = c->vc.vBuffer[i].texture[0].x;
+            GLfixed v = c->vc.vBuffer[i].texture[0].y;
+            if (u != *pExpected++ || v != *pExpected++) {
+                return false;
+            }
+        }
+    }
+
+    static const int tmu = 0;
+    texture_unit_t& u(c->textures.tmu[tmu]);
+    EGLTextureObject* textureObject = u.texture;
+
+    GLint tWidth = textureObject->surface.width;
+    GLint tHeight = textureObject->surface.height;
+    GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight};
+
+    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
+    y = cbSurface.height - (y + h);
+
+    return copybit(x, y, w, h, textureObject, crop_rect,
+            COPYBIT_TRANSFORM_ROT_90, c);
+}
+
+/*
+ * Try to drawTexiOESWithCopybit, return false if we fail.
+ */
+
+bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
+        GLint w, GLint h, ogles_context_t* c)
+{
+    // quickly process empty rects
+    if ((w|h) <= 0) {
+        return true;
+    }
+
+    if (! checkContext(c)) {
+        return false;
+    }
+
+    static const int tmu = 0;
+    texture_unit_t& u(c->textures.tmu[tmu]);
+    EGLTextureObject* textureObject = u.texture;
+
+    return copybit(x, y, w, h, textureObject, textureObject->crop_rect,
+            0, c);
+}
+
+} // namespace android
+
diff --git a/opengl/libagl/copybit.h b/opengl/libagl/copybit.h
new file mode 100644
index 0000000..1888aee
--- /dev/null
+++ b/opengl/libagl/copybit.h
@@ -0,0 +1,75 @@
+/*
+**
+** 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.
+*/
+
+#ifndef ANDROID_OPENGLES_COPYBIT_H
+#define ANDROID_OPENGLES_COPYBIT_H
+
+#include <stdlib.h>
+
+#include <GLES/gl.h>
+
+#include "TextureObjectManager.h"
+namespace android {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+
+bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
+        GLint w, GLint h, ogles_context_t* c);
+bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first,
+        GLsizei count);
+
+inline bool copybitQuickCheckContext(ogles_context_t* c) {
+        return  c->copybits.drawSurfaceFd >= 0
+            && c->rasterizer.state.enabled_tmu == 1
+            && c->textures.tmu[0].texture->copybits_fd >= 0;
+}
+
+/*
+ * Tries to draw a drawTexiOES using copybit hardware.
+ * Returns true if successful.
+ */
+inline bool drawTexiOESWithCopybit(GLint x, GLint y, GLint z,
+        GLint w, GLint h, ogles_context_t* c) {
+    if (!copybitQuickCheckContext(c)) {
+    	return false;
+   	}
+   	
+   	return drawTexiOESWithCopybit_impl(x, y, z, w, h, c);
+}
+
+/*
+ * Tries to draw a triangle fan using copybit hardware.
+ * Returns true if successful.
+ */
+inline bool drawTrangleFanWithCopybit(ogles_context_t* c, GLint first,
+        GLsizei count) {
+    /*
+     * We are looking for the glDrawArrays call made by SurfaceFlinger.
+     */
+
+    if (!(copybitQuickCheckContext(c) && first == 0 && count == 4)) {
+        return false;
+    }
+    
+    return drawTrangleFanWithCopybit_impl(c, first, count);
+}
+
+
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
+} // namespace android
+
+#endif // ANDROID_OPENGLES_COPYBIT_H
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index c44478d..0df2bba 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -15,8 +15,6 @@
 ** limitations under the License.
 */
 
-#define LOG_TAG "EGL"
-
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -41,11 +39,17 @@
 #include <pixelflinger/format.h>
 #include <pixelflinger/pixelflinger.h>
 
+#include <private/ui/android_natives_priv.h>
+
 #include "context.h"
 #include "state.h"
 #include "texture.h"
 #include "matrix.h"
 
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include "gralloc_priv.h"
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
 #undef NELEM
 #define NELEM(x) (sizeof(x)/sizeof(*(x)))
 
@@ -89,9 +93,9 @@
 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;
     }
@@ -140,18 +144,20 @@
                 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
     virtual     ~egl_surface_t();
     virtual     bool    isValid() const = 0;
-    
+
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl) = 0;
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl) = 0;
+    virtual     void        connect() {}
+    virtual     void        disconnect() {}
     virtual     EGLint      getWidth() const = 0;
     virtual     EGLint      getHeight() const = 0;
-    virtual     void*       getBits() 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;
 };
@@ -185,42 +191,161 @@
 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_t : public egl_surface_t
+struct egl_window_surface_v2_t : public egl_surface_t
 {
-    egl_window_surface_t(
+    egl_window_surface_v2_t(
             EGLDisplay dpy, EGLConfig config,
             int32_t depthFormat,
-            egl_native_window_t* window);
+            android_native_window_t* window);
 
-     ~egl_window_surface_t();
+     ~egl_window_surface_v2_t();
 
-    virtual     bool        isValid() const { return nativeWindow->magic == 0x600913; }    
+    virtual     bool        isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; }
     virtual     EGLBoolean  swapBuffers();
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
-    virtual     EGLint      getWidth() const    { return nativeWindow->width;  }
-    virtual     EGLint      getHeight() const   { return nativeWindow->height; }
-    virtual     void*       getBits() const;
+    virtual     void        connect();
+    virtual     void        disconnect();
+    virtual     EGLint      getWidth() const    { return buffer->width;  }
+    virtual     EGLint      getHeight() const   { return buffer->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:
-    egl_native_window_t*    nativeWindow;
+    status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
+    status_t unlock(android_native_buffer_t* buf);
+    android_native_window_t*   nativeWindow;
+    android_native_buffer_t*   buffer;
+    android_native_buffer_t*   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) { }
+        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 = max(lhs.top, rhs.top);
+                    storage++;
+                }
+                if (lhs.left < rhs.left) { // left-side rect
+                    storage->left   = lhs.left;
+                    storage->top    = max(lhs.top, rhs.top);
+                    storage->right  = max(lhs.left, rhs.left);
+                    storage->bottom = min(lhs.bottom, rhs.bottom);
+                    storage++;
+                }
+                if (lhs.right > rhs.right) { // right-side rect
+                    storage->left   = min(lhs.right, rhs.right);
+                    storage->top    = max(lhs.top, rhs.top);
+                    storage->right  = lhs.right;
+                    storage->bottom = min(lhs.bottom, rhs.bottom);
+                    storage++;
+                }
+                if (lhs.bottom > rhs.bottom) { // bottom rect
+                    storage->left   = lhs.left;
+                    storage->top    = min(lhs.bottom, rhs.bottom);
+                    storage->right  = lhs.right;
+                    storage->bottom = lhs.bottom;
+                    storage++;
+                }
+                reg.count = storage - reg.storage;
+            }
+            return reg;
+        }
+        bool isEmpty() const {
+            return count<=0;
+        }
+        ssize_t getRects(Rect const* * rects) const {
+            *rects = storage;
+            return count;
+        }
+    private:
+        Rect storage[4];
+        ssize_t count;
+    };
+    
+    void copyBlt(
+            android_native_buffer_t* dst, void* dst_vaddr,
+            android_native_buffer_t* src, void const* src_vaddr,
+            const Rect* reg, ssize_t count);
+
+    Rect dirtyRegion;
+    Rect oldDirtyRegion;
 };
 
-egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy,
+egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
         EGLConfig config,
         int32_t depthFormat,
-        egl_native_window_t* window)
-    : egl_surface_t(dpy, config, depthFormat), nativeWindow(window)
+        android_native_window_t* window)
+    : egl_surface_t(dpy, config, depthFormat), 
+    nativeWindow(window), buffer(0), previousBuffer(0), module(0),
+    bits(NULL)
 {
+    hw_module_t const* pModule;
+    hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
+    module = reinterpret_cast<gralloc_module_t const*>(pModule);
+
+    pixelFormatTable = gglGetPixelFormatTable();
+    
+    // keep a reference on the window
+    nativeWindow->common.incRef(&nativeWindow->common);
+
+    // dequeue a buffer
+    nativeWindow->dequeueBuffer(nativeWindow, &buffer);
+
+    // allocate a corresponding depth-buffer
+    width = buffer->width;
+    height = buffer->height;
     if (depthFormat) {
-        depth.width   = window->width;
-        depth.height  = window->height;
+        depth.width   = width;
+        depth.height  = height;
         depth.stride  = depth.width; // use the width here
         depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
         if (depth.data == 0) {
@@ -228,76 +353,258 @@
             return;
         }
     }
-    nativeWindow->incRef(nativeWindow);
-}
-egl_window_surface_t::~egl_window_surface_t() {
-    nativeWindow->decRef(nativeWindow);
+
+    // keep a reference on the buffer
+    buffer->common.incRef(&buffer->common);
 }
 
-EGLBoolean egl_window_surface_t::swapBuffers()
+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);
+}
+
+void egl_window_surface_v2_t::connect() 
 {
-    uint32_t flags = nativeWindow->swapBuffers(nativeWindow);
-    if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) {
+    // 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("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
+                buffer, buffer->width, buffer->height);
+        setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
+        // FIXME: we should make sure we're not accessing the buffer anymore
+    }
+}
+
+void egl_window_surface_v2_t::disconnect() 
+{
+    if (buffer && bits) {
+        bits = NULL;
+        unlock(buffer);
+    }
+}
+
+status_t egl_window_surface_v2_t::lock(
+        android_native_buffer_t* buf, int usage, void** vaddr)
+{
+    int err = module->lock(module, buf->handle, 
+            usage, 0, 0, buf->width, buf->height, vaddr);
+    return err;
+}
+
+status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
+{
+    int err = module->unlock(module, buf->handle);
+    return err;
+}
+
+void egl_window_surface_v2_t::copyBlt(
+        android_native_buffer_t* dst, void* dst_vaddr,
+        android_native_buffer_t* src, void const* src_vaddr,
+        const Rect* reg, ssize_t count)
+{
+    // FIXME: use copybit if possible
+    // NOTE: dst and src must be the same format
+    
+    Rect r;
+    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;
+    
+    for (int i= 0 ; i<count ; i++) {
+        const Rect& r(reg[i]);
+        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()
+{
+    /*
+     * Handle eglSetSwapRectangleANDROID()
+     * We copyback from the front buffer 
+     */
+    if (!dirtyRegion.isEmpty()) {
+        dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
+        if (previousBuffer) {
+            const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
+            if (!copyBack.isEmpty()) {
+                Rect const* list;
+                ssize_t count = copyBack.getRects(&list);
+                // copy from previousBuffer to buffer
+                void* prevBits;
+                if (lock(previousBuffer, 
+                        GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) 
+                {
+                    copyBlt(buffer, bits, previousBuffer, prevBits, list, count);
+                    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
+    nativeWindow->dequeueBuffer(nativeWindow, &buffer);
+    
+    // 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   = nativeWindow->width;
-            depth.height  = nativeWindow->height;
-            depth.stride  = nativeWindow->stride;
+            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_NO_SURFACE);
+                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);
+        setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
+        // FIXME: we should make sure we're not accessing the buffer anymore
+    }
+
     return EGL_TRUE;
 }
 
-EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl)
+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;
+}
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+
+static bool supportedCopybitsDestinationFormat(int format) {
+    // Hardware supported and no destination alpha
+    switch (format) {
+    case HAL_PIXEL_FORMAT_RGB_565:
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        return true;
+    default:
+        return false;
+    }
+}
+#endif
+
+EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl)
 {
     GGLSurface buffer;
     buffer.version = sizeof(GGLSurface);
-    buffer.width   = nativeWindow->width;
-    buffer.height  = nativeWindow->height;
-    buffer.stride  = nativeWindow->stride;
-    buffer.data    = (GGLubyte*)nativeWindow->base + nativeWindow->offset;
-    buffer.format  = nativeWindow->format;
+    buffer.width   = this->buffer->width;
+    buffer.height  = this->buffer->height;
+    buffer.stride  = this->buffer->stride;
+    buffer.data    = (GGLubyte*)bits;
+    buffer.format  = this->buffer->format;
     gl->rasterizer.procs.colorBuffer(gl, &buffer);
     if (depth.data != gl->rasterizer.state.buffers.depth.data)
         gl->rasterizer.procs.depthBuffer(gl, &depth);
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    gl->copybits.drawSurfaceFd = -1;
+    if (supportedCopybitsDestinationFormat(buffer.format)) {
+        buffer_handle_t handle = this->buffer->handle;
+        if (handle != NULL) {
+            private_handle_t* hand = private_handle_t::dynamicCast(handle);
+            if (hand != NULL) {
+                if (hand->usesPhysicallyContiguousMemory()) {
+                    gl->copybits.drawSurfaceFd = hand->fd;
+                }
+            }
+        }
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
     return EGL_TRUE;
 }
-EGLBoolean egl_window_surface_t::bindReadSurface(ogles_context_t* gl)
+EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl)
 {
     GGLSurface buffer;
     buffer.version = sizeof(GGLSurface);
-    buffer.width   = nativeWindow->width;
-    buffer.height  = nativeWindow->height;
-    buffer.stride  = nativeWindow->stride;
-    buffer.data    = (GGLubyte*)nativeWindow->base + nativeWindow->offset;
-    buffer.format  = nativeWindow->format;
+    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  = this->buffer->format;
     gl->rasterizer.procs.readBuffer(gl, &buffer);
     return EGL_TRUE;
 }
-void* egl_window_surface_t::getBits() const {
-    return (GGLubyte*)nativeWindow->base + nativeWindow->offset;
-}
-EGLint egl_window_surface_t::getHorizontalResolution() const {
+EGLint egl_window_surface_v2_t::getHorizontalResolution() const {
     return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
 }
-EGLint egl_window_surface_t::getVerticalResolution() const {
+EGLint egl_window_surface_v2_t::getVerticalResolution() const {
     return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
 }
-EGLint egl_window_surface_t::getRefreshRate() const {
-    return (nativeWindow->fps * EGL_DISPLAY_SCALING);
+EGLint egl_window_surface_v2_t::getRefreshRate() const {
+    return (60 * EGL_DISPLAY_SCALING); // FIXME
 }
-EGLint egl_window_surface_t::getSwapBehavior() const {
-    uint32_t flags = nativeWindow->flags;
-    if (flags & EGL_NATIVES_FLAG_DESTROY_BACKBUFFER)
-        return EGL_BUFFER_DESTROYED;
-    return EGL_BUFFER_PRESERVED;
+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;
 }
 
 // ----------------------------------------------------------------------------
@@ -311,12 +618,11 @@
 
     virtual ~egl_pixmap_surface_t() { }
 
-    virtual     bool        isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }    
+    virtual     bool        isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
     virtual     EGLint      getWidth() const    { return nativePixmap.width;  }
     virtual     EGLint      getHeight() const   { return nativePixmap.height; }
-    virtual     void*       getBits() const     { return nativePixmap.data; }
 private:
     egl_native_pixmap_t     nativePixmap;
 };
@@ -347,7 +653,7 @@
     buffer.stride  = nativePixmap.stride;
     buffer.data    = nativePixmap.data;
     buffer.format  = nativePixmap.format;
-    
+
     gl->rasterizer.procs.colorBuffer(gl, &buffer);
     if (depth.data != gl->rasterizer.state.buffers.depth.data)
         gl->rasterizer.procs.depthBuffer(gl, &depth);
@@ -376,12 +682,11 @@
 
     virtual ~egl_pbuffer_surface_t();
 
-    virtual     bool        isValid() const { return pbuffer.data != 0; }    
+    virtual     bool        isValid() const { return pbuffer.data != 0; }
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
     virtual     EGLint      getWidth() const    { return pbuffer.width;  }
     virtual     EGLint      getHeight() const   { return pbuffer.height; }
-    virtual     void*       getBits() const     { return pbuffer.data; }
 private:
     GGLSurface  pbuffer;
 };
@@ -407,7 +712,7 @@
     pbuffer.stride  = w;
     pbuffer.data    = (GGLubyte*)malloc(size);
     pbuffer.format  = f;
-    
+
     if (depthFormat) {
         depth.width   = pbuffer.width;
         depth.height  = pbuffer.height;
@@ -468,7 +773,12 @@
 static char const * const gVendorString     = "Google Inc.";
 static char const * const gVersionString    = "1.2 Android Driver";
 static char const * const gClientApiString  = "OpenGL ES";
-static char const * const gExtensionsString = "";
+static char const * const gExtensionsString =
+        "EGL_KHR_image_base "
+        // "KHR_image_pixmap "
+        "EGL_ANDROID_image_native_buffer "
+        "EGL_ANDROID_swap_rectangle "
+        ;
 
 // ----------------------------------------------------------------------------
 
@@ -496,6 +806,10 @@
             (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
     { "glQueryMatrixxOES",
             (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
+    { "glEGLImageTargetTexture2DOES",
+            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
+    { "glEGLImageTargetRenderbufferStorageOES",
+            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
     { "glClipPlanef",
             (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
     { "glClipPlanex",
@@ -512,7 +826,7 @@
             (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
 };
 
-/* 
+/*
  * In the lists below, attributes names MUST be sorted.
  * Additionally, all configs must be sorted according to
  * the EGL specification.
@@ -523,7 +837,7 @@
         { EGL_CONFIG_CAVEAT,              EGL_SLOW_CONFIG                   },
         { EGL_LEVEL,                      0                                 },
         { EGL_MAX_PBUFFER_HEIGHT,         GGL_MAX_VIEWPORT_DIMS             },
-        { EGL_MAX_PBUFFER_PIXELS,         
+        { 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                          },
@@ -660,9 +974,9 @@
 {
    while (first <= last) {
        int mid = (first + last) / 2;
-       if (key > sortedArray[mid].key) { 
+       if (key > sortedArray[mid].key) {
            first = mid + 1;
-       } else if (key < sortedArray[mid].key) { 
+       } else if (key < sortedArray[mid].key) {
            last = mid - 1;
        } else {
            return mid;
@@ -674,13 +988,13 @@
 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; 
+    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; 
+        configFound = config_base_attribute_list;
         index = binarySearch<config_pair_t>(
                 config_base_attribute_list,
                 0, NELEM(config_base_attribute_list)-1,
@@ -794,28 +1108,28 @@
     int32_t depthFormat;
     int32_t pixelFormat;
     switch(configID) {
-    case 0: 
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
+    case 0:
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
         depthFormat = 0;
         break;
     case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
         depthFormat = 0;
         break;
     case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
         depthFormat = 0;
         break;
     case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     default:
@@ -828,9 +1142,9 @@
     //if (EGLint(info.format) != pixelFormat)
     //    return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
 
-    egl_surface_t* surface =
-        new egl_window_surface_t(dpy, config, depthFormat,
-                static_cast<egl_native_window_t*>(window));
+    egl_surface_t* surface;
+    surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
+            static_cast<android_native_window_t*>(window));
 
     if (!surface->isValid()) {
         // there was a problem in the ctor, the error
@@ -863,28 +1177,28 @@
     int32_t depthFormat;
     int32_t pixelFormat;
     switch(configID) {
-    case 0: 
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
+    case 0:
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
         depthFormat = 0;
         break;
     case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
         depthFormat = 0;
         break;
     case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
         depthFormat = 0;
         break;
     case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     default:
@@ -916,10 +1230,10 @@
     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;
@@ -927,28 +1241,28 @@
     int32_t depthFormat;
     int32_t pixelFormat;
     switch(configID) {
-    case 0: 
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
+    case 0:
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
         depthFormat = 0;
         break;
     case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
         depthFormat = 0;
         break;
     case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
         depthFormat = 0;
         break;
     case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
     default:
@@ -1001,7 +1315,7 @@
         egl_display_t& d = egl_display_t::get_display(dpy);
         d.type = display;
         return dpy;
-    }    
+    }
     return EGL_NO_DISPLAY;
 }
 
@@ -1009,10 +1323,10 @@
 {
     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);
@@ -1080,7 +1394,7 @@
         *num_config = 0;
         return EGL_TRUE;
     }
-    
+
     int numAttributes = 0;
     int numConfigs =  NELEM(gConfigs);
     uint32_t possibleMatch = (1<<numConfigs)-1;
@@ -1161,7 +1475,7 @@
 {
     return createWindowSurface(dpy, config, window, attrib_list);
 }
-    
+
 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
                                     NativePixmapType pixmap,
                                     const EGLint *attrib_list)
@@ -1174,7 +1488,7 @@
 {
     return createPbufferSurface(dpy, config, attrib_list);
 }
-                                    
+
 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
 {
     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
@@ -1185,6 +1499,11 @@
             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;
@@ -1244,7 +1563,7 @@
             *value = (wr * EGL_DISPLAY_SCALING) / hr;
         } break;
         case EGL_SWAP_BEHAVIOR:
-            *value = surface->getSwapBehavior(); 
+            *value = surface->getSwapBehavior();
             break;
         default:
             ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
@@ -1294,7 +1613,7 @@
     }
 
     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);
 
@@ -1310,21 +1629,28 @@
         egl_surface_t* r = (egl_surface_t*)read;
         if ((d && d->ctx && d->ctx != ctx) ||
             (r && r->ctx && r->ctx != ctx)) {
-            // once of the surface is bound to a context in another thread
+            // one of the surface is bound to a context in another thread
             return setError(EGL_BAD_ACCESS, EGL_FALSE);
         }
     }
 
-    // TODO: call connect / disconnect on the surface
-
     ogles_context_t* gl = (ogles_context_t*)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;
-            c->read = read;
+            
+            if (c->draw) {
+                reinterpret_cast<egl_surface_t*>(c->draw)->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;
@@ -1338,10 +1664,12 @@
                 ogles_scissor(gl, 0, 0, w, h);
             }
             if (d) {
+                d->connect();
                 d->ctx = ctx;
                 d->bindDrawSurface(gl);
             }
             if (r) {
+                // FIXME: lock/connect the read surface too 
                 r->ctx = ctx;
                 r->bindReadSurface(gl);
             }
@@ -1352,8 +1680,16 @@
                 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) d->ctx = EGL_NO_CONTEXT;
-                if (r) r->ctx = EGL_NO_CONTEXT;
+                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;
@@ -1425,7 +1761,7 @@
 {
     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->dpy != dpy)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1558,7 +1894,7 @@
 }
 
 // ----------------------------------------------------------------------------
-// Android extensions
+// EGL_EGLEXT_VERSION 3
 // ----------------------------------------------------------------------------
 
 void (*eglGetProcAddress (const char *procname))()
@@ -1571,3 +1907,80 @@
     }
     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);
+    }
+
+    android_native_buffer_t* native_buffer = (android_native_buffer_t*)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))
+        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);
+    }
+
+    android_native_buffer_t* native_buffer = (android_native_buffer_t*)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))
+        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->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/libagl/state.cpp b/opengl/libagl/state.cpp
index 5cbabea..a00f779 100644
--- a/opengl/libagl/state.cpp
+++ b/opengl/libagl/state.cpp
@@ -2,16 +2,16 @@
 **
 ** 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.
 */
 
@@ -28,12 +28,16 @@
 #include "BufferObjectManager.h"
 #include "TextureObjectManager.h"
 
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include <hardware/copybit.h>
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
 namespace android {
 
 // ----------------------------------------------------------------------------
 
 static char const * const gVendorString     = "Android";
-static char const * const gRendererString   = "Android PixelFlinger 1.0";
+static char const * const gRendererString   = "Android PixelFlinger 1.1";
 static char const * const gVersionString    = "OpenGL ES-CM 1.0";
 static char const * const gExtensionsString =
     "GL_OES_byte_coordinates "              // OK
@@ -46,9 +50,9 @@
     "GL_OES_query_matrix "                  // OK
     //        "GL_OES_point_size_array "              // TODO
     //        "GL_OES_point_sprite "                  // TODO
+    "GL_OES_EGL_image "                     // OK
     "GL_ARB_texture_compression "           // OK
     "GL_ARB_texture_non_power_of_two "      // OK
-    "GL_ANDROID_direct_texture "            // OK
     "GL_ANDROID_user_clip_plane "           // OK
     "GL_ANDROID_vertex_buffer_object "      // OK
     "GL_ANDROID_generate_mipmap "           // OK
@@ -62,13 +66,13 @@
 ogles_context_t *ogles_init(size_t extra)
 {
     void* const base = malloc(extra + sizeof(ogles_context_t) + 32);
-	if (!base) return 0;
+    if (!base) return 0;
 
     ogles_context_t *c =
             (ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL);
     memset(c, 0, sizeof(ogles_context_t));
     ggl_init_context(&(c->rasterizer));
-    
+
     // XXX: this should be passed as an argument
     sp<EGLSurfaceManager> smgr(new EGLSurfaceManager());
     c->surfaceManager = smgr.get();
@@ -87,13 +91,42 @@
     c->rasterizer.base = base;
     c->point.size = TRI_ONE;
     c->line.width = TRI_ONE;
-            
+
     // in OpenGL, writing to the depth buffer is enabled by default.
     c->rasterizer.procs.depthMask(c, 1);
-    
+
     // OpenGL enables dithering by default
     c->rasterizer.procs.enable(c, GL_DITHER);
 
+    c->copybits.blitEngine = NULL;
+    c->copybits.minScale = 0;
+    c->copybits.maxScale = 0;
+    c->copybits.drawSurfaceFd = -1;
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    hw_module_t const* module;
+    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+        struct copybit_device_t* copyBits;
+        if (copybit_open(module, &copyBits) == 0) {
+            c->copybits.blitEngine = copyBits;
+            {
+                int minLim = copyBits->get(copyBits,
+                        COPYBIT_MINIFICATION_LIMIT);
+                if (minLim != -EINVAL && minLim > 0) {
+                    c->copybits.minScale = (1 << 16) / minLim;
+                }
+            }
+            {
+                int magLim = copyBits->get(copyBits,
+                        COPYBIT_MAGNIFICATION_LIMIT);
+                if (magLim != -EINVAL && magLim > 0) {
+                    c->copybits.maxScale = min(32*1024-1, magLim) << 16;
+                }
+            }
+        }
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
     return c;
 }
 
@@ -107,7 +140,12 @@
     c->surfaceManager->decStrong(c);
     c->bufferObjectManager->decStrong(c);
     ggl_uninit_context(&(c->rasterizer));
-	free(c->rasterizer.base);
+    free(c->rasterizer.base);
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    if (c->copybits.blitEngine != NULL) {
+        copybit_close((struct copybit_device_t*) c->copybits.blitEngine);
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
 }
 
 void _ogles_error(ogles_context_t* c, GLenum error)
@@ -188,7 +226,7 @@
         // these need to fall through into the rasterizer
         c->rasterizer.procs.enableDisable(c, cap, enabled);
         break;
-        
+
     case GL_MULTISAMPLE:
     case GL_SAMPLE_ALPHA_TO_COVERAGE:
     case GL_SAMPLE_ALPHA_TO_ONE:
@@ -281,7 +319,7 @@
     case GL_LINE_SMOOTH_HINT:
         break;
     case GL_POINT_SMOOTH_HINT:
-        c->rasterizer.procs.enableDisable(c, 
+        c->rasterizer.procs.enableDisable(c,
                 GGL_POINT_SMOOTH_NICE, mode==GL_NICEST);
         break;
     case GL_PERSPECTIVE_CORRECTION_HINT:
@@ -323,7 +361,7 @@
         c->error = 0;
         return ret;
     }
-    
+
     if (c->rasterizer.error) {
         const GLenum ret(c->rasterizer.error);
         c->rasterizer.error = 0;
@@ -362,25 +400,25 @@
         int index = c->rasterizer.state.buffers.color.format;
         GGLFormat const * formats = gglGetPixelFormatTable();
         params[0] = formats[index].ah - formats[index].al;
-        break; 
+        break;
         }
     case GL_RED_BITS: {
         int index = c->rasterizer.state.buffers.color.format;
         GGLFormat const * formats = gglGetPixelFormatTable();
         params[0] = formats[index].rh - formats[index].rl;
-        break; 
+        break;
         }
     case GL_GREEN_BITS: {
         int index = c->rasterizer.state.buffers.color.format;
         GGLFormat const * formats = gglGetPixelFormatTable();
         params[0] = formats[index].gh - formats[index].gl;
-        break; 
+        break;
         }
     case GL_BLUE_BITS: {
         int index = c->rasterizer.state.buffers.color.format;
         GGLFormat const * formats = gglGetPixelFormatTable();
         params[0] = formats[index].bh - formats[index].bl;
-        break; 
+        break;
         }
     case GL_COMPRESSED_TEXTURE_FORMATS:
         params[ 0] = GL_PALETTE4_RGB8_OES;
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index b6f534b..d675107 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -2,16 +2,16 @@
 **
 ** 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.
 */
 
@@ -23,6 +23,13 @@
 #include "texture.h"
 #include "TextureObjectManager.h"
 
+#include <private/ui/android_natives_priv.h>
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include "copybit.h"
+#include "gralloc_priv.h"
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -48,7 +55,7 @@
     // each context has a default named (0) texture (not shared)
     c->textures.defaultTexture = new EGLTextureObject();
     c->textures.defaultTexture->incStrong(c);
-    
+
     // bind the default texture to each texture unit
     for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
         bindTextureTmu(c, i, 0, c->textures.defaultTexture);
@@ -96,7 +103,7 @@
     }
 }
 
-void ogles_validate_texture_impl(ogles_context_t* c)
+void ogles_validate_texture(ogles_context_t* c)
 {
     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
         if (c->rasterizer.state.texture[i].enable)
@@ -110,6 +117,66 @@
     c->textures.tmu[tmu].dirty = flags;
 }
 
+/*
+ * If the active textures are EGLImage, they need to be locked before
+ * they can be used. 
+ * 
+ * FIXME: code below is far from being optimal
+ * 
+ */
+
+void ogles_lock_textures(ogles_context_t* c)
+{
+    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;
+            if (native_buffer) {
+                c->rasterizer.procs.activeTexture(c, i);
+                hw_module_t const* pModule;
+                if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
+                    continue;
+
+                gralloc_module_t const* module =
+                    reinterpret_cast<gralloc_module_t const*>(pModule);
+
+                void* vaddr;
+                int err = module->lock(module, native_buffer->handle,
+                        GRALLOC_USAGE_SW_READ_OFTEN,
+                        0, 0, native_buffer->width, native_buffer->height,
+                        &vaddr);
+
+                u.texture->setImageBits(vaddr);
+                c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
+            }
+        }
+    }
+}
+
+void ogles_unlock_textures(ogles_context_t* c)
+{
+    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;
+            if (native_buffer) {
+                c->rasterizer.procs.activeTexture(c, i);
+                hw_module_t const* pModule;
+                if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
+                    continue;
+
+                gralloc_module_t const* module =
+                    reinterpret_cast<gralloc_module_t const*>(pModule);
+
+                module->unlock(module, native_buffer->handle);
+                u.texture->setImageBits(NULL);
+                c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
+            }
+        }
+    }
+    c->rasterizer.procs.activeTexture(c, c->textures.active);
+}
+
 // ----------------------------------------------------------------------------
 #if 0
 #pragma mark -
@@ -255,7 +322,7 @@
         u.texture->decStrong(c);
 
     if (name == 0) {
-        // 0 is our local texture object, not shared with anyone. 
+        // 0 is our local texture object, not shared with anyone.
         // But it affects all bound TMUs immediately.
         // (we need to invalidate all units bound to this texture object)
         tex = c->textures.defaultTexture;
@@ -273,7 +340,7 @@
     u.texture = tex.get();
     u.texture->incStrong(c);
     u.name = name;
-    invalidate_texture(c, active);    
+    invalidate_texture(c, active);
     return tex;
 }
 
@@ -282,7 +349,7 @@
 {
     if (tex.get() == c->textures.tmu[tmu].texture)
         return;
-    
+
     // free the reference to the previously bound object
     texture_unit_t& u(c->textures.tmu[tmu]);
     if (u.texture)
@@ -310,7 +377,7 @@
     if (formatIdx == 0) { // we don't know what to do with this
         return GL_INVALID_OPERATION;
     }
-    
+
     // figure out the size we need as well as the stride
     const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
     const int32_t align = c->textures.unpackAlignment-1;
@@ -530,8 +597,8 @@
         ogles_error(c, GL_INVALID_ENUM);
         return;
     }
-    
-    EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;    
+
+    EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;
     switch (pname) {
     case GL_TEXTURE_WRAP_S:
         if ((param == GL_REPEAT) ||
@@ -581,13 +648,12 @@
 }
 
 
-static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
+
+static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
         ogles_context_t* c)
 {
-    // quickly reject empty rects
-    if ((w|h) <= 0)
-        return;                
-
+    ogles_lock_textures(c);
+    
     const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
     y = gglIntToFixed(cbSurface.height) - (y + h);
     w >>= FIXED_BITS;
@@ -610,7 +676,7 @@
                 GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP);
         u.dirty = 0xFF; // XXX: should be more subtle
 
-        EGLTextureObject* textureObject = u.texture;  
+        EGLTextureObject* textureObject = u.texture;
         const GLint Ucr = textureObject->crop_rect[0] << 16;
         const GLint Vcr = textureObject->crop_rect[1] << 16;
         const GLint Wcr = textureObject->crop_rect[2] << 16;
@@ -641,11 +707,30 @@
     c->rasterizer.procs.disable(c, GGL_W_LERP);
     c->rasterizer.procs.disable(c, GGL_AA);
     c->rasterizer.procs.shadeModel(c, GL_FLAT);
-    c->rasterizer.procs.recti(c, 
+    c->rasterizer.procs.recti(c,
             gglFixedToIntRound(x),
             gglFixedToIntRound(y),
             gglFixedToIntRound(x)+w,
             gglFixedToIntRound(y)+h);
+
+    ogles_unlock_textures(c);
+}
+
+static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
+        ogles_context_t* c)
+{
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    if (drawTexiOESWithCopybit(gglFixedToIntRound(x),
+            gglFixedToIntRound(y), gglFixedToIntRound(z),
+            gglFixedToIntRound(w), gglFixedToIntRound(h), c)) {
+        return;
+    }
+#else
+    // quickly reject empty rects
+    if ((w|h) <= 0)
+        return;
+#endif
+    drawTexxOESImp(x, y, z, w, h, c);
 }
 
 static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c)
@@ -656,14 +741,21 @@
     // which is a lot faster.
 
     if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+        if (drawTexiOESWithCopybit(x, y, z, w, h, c)) {
+            return;
+        }
+#endif
         const int tmu = 0;
         texture_unit_t& u(c->textures.tmu[tmu]);
-        EGLTextureObject* textureObject = u.texture;  
+        EGLTextureObject* textureObject = u.texture;
         const GLint Wcr = textureObject->crop_rect[2];
         const GLint Hcr = textureObject->crop_rect[3];
 
         if ((w == Wcr) && (h == -Hcr)) {
+#ifndef LIBAGL_USE_GRALLOC_COPYBITS
             if ((w|h) <= 0) return; // quickly reject empty rects
+#endif
 
             if (u.dirty) {
                 c->rasterizer.procs.activeTexture(c, tmu);
@@ -679,14 +771,14 @@
                     GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
             u.dirty = 0xFF; // XXX: should be more subtle
             c->rasterizer.procs.activeTexture(c, c->textures.active);
-            
+
             const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
             y = cbSurface.height - (y + h);
             const GLint Ucr = textureObject->crop_rect[0];
             const GLint Vcr = textureObject->crop_rect[1];
             const GLint s0  = Ucr - x;
             const GLint t0  = (Vcr + Hcr) - y;
-            
+
             const GLuint tw = textureObject->surface.width;
             const GLuint th = textureObject->surface.height;
             if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) {
@@ -694,7 +786,9 @@
                 // in this case, so we just use the slow case, which
                 // at least won't crash
                 goto slow_case;
-            } 
+            }
+
+            ogles_lock_textures(c);
 
             c->rasterizer.procs.texCoord2i(c, s0, t0);
             const uint32_t enables = c->rasterizer.state.enables;
@@ -706,12 +800,15 @@
             c->rasterizer.procs.disable(c, GGL_AA);
             c->rasterizer.procs.shadeModel(c, GL_FLAT);
             c->rasterizer.procs.recti(c, x, y, x+w, y+h);
+            
+            ogles_unlock_textures(c);
+
             return;
         }
     }
 
 slow_case:
-    drawTexxOES(
+    drawTexxOESImp(
             gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z),
             gglIntToFixed(w), gglIntToFixed(h),
             c);
@@ -749,7 +846,7 @@
     }
 
     // Bind or create a texture
-    sp<EGLTextureObject> tex;    
+    sp<EGLTextureObject> tex;
     if (texture == 0) {
         // 0 is our local texture object
         tex = c->textures.defaultTexture;
@@ -837,7 +934,7 @@
     if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) {
         ogles_error(c, GL_INVALID_ENUM);
         return;
-    }    
+    }
     if ((param<=0 || param>8) || (param & (param-1))) {
         ogles_error(c, GL_INVALID_VALUE);
         return;
@@ -945,7 +1042,7 @@
     }
 
     // "uncompress" the texture since pixelflinger doesn't support
-    // any compressed texture format natively. 
+    // any compressed texture format natively.
     GLenum format;
     GLenum type;
     switch (internalformat) {
@@ -1009,7 +1106,7 @@
         GLenum format, GLenum type, const GLvoid *pixels)
 {
     ogles_context_t* c = ogles_context_t::get();
-    if (target != GL_TEXTURE_2D && target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
+    if (target != GL_TEXTURE_2D) {
         ogles_error(c, GL_INVALID_ENUM);
         return;
     }
@@ -1017,7 +1114,7 @@
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
-    if (format != internalformat) {
+    if (format != (GLenum)internalformat) {
         ogles_error(c, GL_INVALID_OPERATION);
         return;
     }
@@ -1027,16 +1124,10 @@
 
     int32_t size = 0;
     GGLSurface* surface = 0;
-    if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
-        int error = createTextureSurface(c, &surface, &size,
-                level, format, type, width, height);
-        if (error) {
-            ogles_error(c, error);
-            return;
-        }
-    } else if (pixels == 0 || level != 0) {
-        // pixel can't be null for direct texture
-        ogles_error(c, GL_INVALID_OPERATION);
+    int error = createTextureSurface(c, &surface, &size,
+            level, format, type, width, height);
+    if (error) {
+        ogles_error(c, error);
         return;
     }
 
@@ -1057,18 +1148,12 @@
         userSurface.compressedFormat = 0;
         userSurface.data = (GLubyte*)pixels;
 
-        if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
-            int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); 
-            if (err) {
-                ogles_error(c, err);
-                return;
-            }
-            generateMipmap(c, level);
-        } else {
-            // bind it to the texture unit
-            sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
-            tex->setSurface(&userSurface);
+        int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height);
+        if (err) {
+            ogles_error(c, err);
+            return;
         }
+        generateMipmap(c, level);
     }
 }
 
@@ -1143,7 +1228,7 @@
 
     int err = copyPixels(c,
             surface, xoffset, yoffset,
-            userSurface, 0, 0, width, height); 
+            userSurface, 0, 0, width, height);
     if (err) {
         ogles_error(c, err);
         return;
@@ -1196,7 +1281,7 @@
     case GL_LUMINANCE_ALPHA:
     case GL_LUMINANCE:
         type = GL_UNSIGNED_BYTE;
-        break;    
+        break;
     }
 
     // figure out the format to use for the new texture
@@ -1206,7 +1291,7 @@
     case GGL_PIXEL_FORMAT_RGBA_5551:
     case GGL_PIXEL_FORMAT_RGBA_4444:
         format = internalformat;
-        break;    
+        break;
     case GGL_PIXEL_FORMAT_RGBX_8888:
     case GGL_PIXEL_FORMAT_RGB_888:
     case GGL_PIXEL_FORMAT_RGB_565:
@@ -1215,7 +1300,7 @@
         case GL_LUMINANCE:
         case GL_RGB:
             format = internalformat;
-            break;    
+            break;
         }
         break;
     }
@@ -1235,7 +1320,7 @@
         ogles_error(c, error);
         return;
     }
-    
+
     // The bottom row is stored first in textures
     GGLSurface txSurface(*surface);
     txSurface.stride = -txSurface.stride;
@@ -1245,7 +1330,7 @@
 
     int err = copyPixels(c,
             txSurface, 0, 0,
-            cbSurface, x, y, cbSurface.width, cbSurface.height);  
+            cbSurface, x, y, cbSurface.width, cbSurface.height);
     if (err) {
         ogles_error(c, err);
     }
@@ -1295,7 +1380,7 @@
 
     int err = copyPixels(c,
             surface, xoffset, yoffset,
-            cbSurface, x, y, width, height);  
+            cbSurface, x, y, width, height);
     if (err) {
         ogles_error(c, err);
         return;
@@ -1365,7 +1450,7 @@
         return;
     }
 
-    ggl->colorBuffer(ggl, &userSurface);  // destination is user buffer 
+    ggl->colorBuffer(ggl, &userSurface);  // destination is user buffer
     ggl->bindTexture(ggl, &readSurface);  // source is read-buffer
     ggl->texCoord2i(ggl, x, readSurface.height - (y + height));
     ggl->recti(ggl, 0, 0, width, height);
@@ -1419,3 +1504,56 @@
     ogles_context_t* c = ogles_context_t::get();
     drawTexxOES(x, y, z, w, h, c);
 }
+
+// ----------------------------------------------------------------------------
+#if 0
+#pragma mark -
+#pragma mark EGL Image Extension
+#endif
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+    ogles_context_t* c = ogles_context_t::get();
+    if (target != GL_TEXTURE_2D) {
+        ogles_error(c, GL_INVALID_ENUM);
+        return;
+    }
+
+    android_native_buffer_t* native_buffer = (android_native_buffer_t*)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)) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+
+    // bind it to the texture unit
+    sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
+    tex->setImage(native_buffer);
+
+    /*
+     * Here an implementation can retrieve the buffer_handle_t of this buffer
+     * which gives it access to an arbitrary-defined kernel resource
+     * (or anything else for that matter).
+     * There needs to be an intimate knowledge between GLES and buffer_handle_t,
+     * so make sure to validate the handle before using it.
+     * Typically, buffer_handle_t comes from the gralloc HAL which is provided
+     * by the implementor of GLES.
+     *
+     */
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    tex->copybits_fd = -1;
+    private_handle_t* hand;
+    if ((hand = private_handle_t::dynamicCast(native_buffer->handle)) != NULL) {
+        if (hand->usesPhysicallyContiguousMemory()) {
+            tex->copybits_fd = hand->fd;
+        }
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+}
+
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+}
diff --git a/opengl/libagl/texture.h b/opengl/libagl/texture.h
index 5c57948..98f7550 100644
--- a/opengl/libagl/texture.h
+++ b/opengl/libagl/texture.h
@@ -32,13 +32,9 @@
 
 void ogles_init_texture(ogles_context_t* c);
 void ogles_uninit_texture(ogles_context_t* c);
-void ogles_validate_texture_impl(ogles_context_t* c);
-
-inline void ogles_validate_texture(ogles_context_t* c) {
-    if (c->rasterizer.state.enables & GGL_ENABLE_TMUS)
-        ogles_validate_texture_impl(c);
-}
-
+void ogles_validate_texture(ogles_context_t* c);
+void ogles_lock_textures(ogles_context_t* c);
+void ogles_unlock_textures(ogles_context_t* c);
 
 }; // namespace android
 
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 02dadbb..e1fd48b 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -1,17 +1,18 @@
 LOCAL_PATH:= $(call my-dir)
 
-#
+###############################################################################
 # Build META EGL library
 #
 
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= 	\
-	EGL/egl.cpp 		\
-	EGL/gpu.cpp			\
+	EGL/egl.cpp 	\
+	EGL/hooks.cpp 	\
+	EGL/Loader.cpp 	\
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils libbinder libui
+LOCAL_SHARED_LIBRARIES += libcutils libutils
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libEGL
 
@@ -19,24 +20,42 @@
 ifeq ($(TARGET_SIMULATOR),true)
 else
     LOCAL_SHARED_LIBRARIES += libdl
-    # we need to access the Bionic private header <bionic_tls.h>
-    LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
+    # we need to access the private Bionic header <bionic_tls.h>
+    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_SHARED_LIBRARY)
+installed_libEGL := $(LOCAL_INSTALLED_MODULE)
 
 
+# OpenGL drivers config file
+ifneq ($(BOARD_EGL_CFG),)
 
-#
-# Build the wrapper OpenGL ES library
+include $(CLEAR_VARS)
+LOCAL_MODULE := egl.cfg
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/egl
+LOCAL_SRC_FILES := ../../../../$(BOARD_EGL_CFG)
+include $(BUILD_PREBUILT)
+
+# make sure we depend on egl.cfg, so it gets installed
+$(installed_libEGL): | egl.cfg
+
+endif
+
+###############################################################################
+# Build the wrapper OpenGL ES 1.x library
 #
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= 	\
-	GLES_CM/gl.cpp.arm 		\
+LOCAL_SRC_FILES:= 		\
+	GLES_CM/gl.cpp.arm 	\
 #
 
 LOCAL_SHARED_LIBRARIES += libcutils libEGL
@@ -47,10 +66,41 @@
 ifeq ($(TARGET_SIMULATOR),true)
 else
     LOCAL_SHARED_LIBRARIES += libdl
-    # we need to access the Bionic private header <bionic_tls.h>
-    LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
+    # we need to access the private Bionic header <bionic_tls.h>
+    LOCAL_C_INCLUDES += bionic/libc/private
 endif
 
+LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS += -fvisibility=hidden
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+###############################################################################
+# Build the wrapper OpenGL ES 2.x library
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= 		\
+	GLES2/gl2.cpp.arm 	\
+#
+
+LOCAL_SHARED_LIBRARIES += libcutils libEGL
+LOCAL_LDLIBS := -lpthread -ldl
+LOCAL_MODULE:= libGLESv2
+
+# needed on sim build because of weird logging issues
+ifeq ($(TARGET_SIMULATOR),true)
+else
+    LOCAL_SHARED_LIBRARIES += libdl
+    # we need to access the private Bionic header <bionic_tls.h>
+    LOCAL_C_INCLUDES += bionic/libc/private
+endif
+
+LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv2\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
new file mode 100644
index 0000000..4f9939f
--- /dev/null
+++ b/opengl/libs/EGL/Loader.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 <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <limits.h>
+
+#include <cutils/log.h>
+
+#include <EGL/egl.h>
+
+#include "hooks.h"
+#include "egl_impl.h"
+
+#include "Loader.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+
+/*
+ * EGL drivers are called
+ * 
+ * /system/lib/egl/lib{[EGL|GLESv1_CM|GLESv2] | GLES}_$TAG.so 
+ * 
+ */
+
+ANDROID_SINGLETON_STATIC_INSTANCE( Loader )
+
+// ----------------------------------------------------------------------------
+
+Loader::driver_t::driver_t(void* gles) 
+{
+    dso[0] = gles;
+    for (size_t i=1 ; i<NELEM(dso) ; i++)
+        dso[i] = 0;
+}
+
+Loader::driver_t::~driver_t() 
+{
+    for (size_t i=0 ; i<NELEM(dso) ; i++) {
+        if (dso[i]) {
+            dlclose(dso[i]);
+            dso[i] = 0;
+        }
+    }
+}
+
+status_t Loader::driver_t::set(void* hnd, int32_t api)
+{
+    switch (api) {
+        case EGL:
+            dso[0] = hnd;
+            break;
+        case GLESv1_CM:
+            dso[1] = hnd;
+            break;
+        case GLESv2:
+            dso[2] = hnd;
+            break;
+        default:
+            return BAD_INDEX;
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+Loader::entry_t::entry_t(int dpy, int impl, const char* tag)
+    : dpy(dpy), impl(impl), tag(tag) {
+}
+
+// ----------------------------------------------------------------------------
+
+Loader::Loader()
+{
+    char line[256];
+    char tag[256];
+    FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
+    if (cfg == NULL) {
+        // default config
+        LOGD("egl.cfg not found, using default config");
+        gConfig.add( entry_t(0, 0, "android") );
+    } else {
+        while (fgets(line, 256, cfg)) {
+            int dpy;
+            int impl;
+            if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
+                //LOGD(">>> %u %u %s", dpy, impl, tag);
+                gConfig.add( entry_t(dpy, impl, tag) );
+            }
+        }
+        fclose(cfg);
+    }
+}
+
+Loader::~Loader()
+{
+}
+
+const char* Loader::getTag(int dpy, int impl)
+{
+    const Vector<entry_t>& cfgs(gConfig);    
+    const size_t c = cfgs.size();
+    for (size_t i=0 ; i<c ; i++) {
+        if (dpy == cfgs[i].dpy)
+            if (impl == cfgs[i].impl)
+                return cfgs[i].tag.string();
+    }
+    return 0;
+}
+
+void* Loader::open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks)
+{
+    /*
+     * TODO: if we don't find display/0, then use 0/0
+     * (0/0 should always work)
+     */
+    
+    void* dso;
+    char path[PATH_MAX];
+    int index = int(display);
+    driver_t* hnd = 0;
+    const char* const format = "egl/lib%s_%s.so";
+    
+    char const* tag = getTag(index, impl);
+    if (tag) {
+        snprintf(path, PATH_MAX, format, "GLES", tag);
+        dso = load_driver(path, hooks, EGL | GLESv1_CM | GLESv2);
+        if (dso) {
+            hnd = new driver_t(dso);
+        } else {
+            // Always load EGL first
+            snprintf(path, PATH_MAX, "lib%s_%s.so", "EGL", tag);
+            dso = load_driver(path, hooks, EGL);
+            if (dso) {
+                hnd = new driver_t(dso);
+
+                // TODO: make this more automated
+                snprintf(path, PATH_MAX, format, "GLESv1_CM", tag);
+                hnd->set( load_driver(path, hooks, GLESv1_CM), GLESv1_CM );
+
+                snprintf(path, PATH_MAX, format, "GLESv2", tag);
+                hnd->set( load_driver(path, hooks, GLESv2), GLESv2 );
+            }
+        }
+    }
+
+    LOG_FATAL_IF(!index && !impl && !hnd, 
+            "couldn't find the default OpenGL ES implementation "
+            "for default display");
+    
+    return (void*)hnd;
+}
+
+status_t Loader::close(void* driver)
+{
+    driver_t* hnd = (driver_t*)driver;
+    delete hnd;
+    return NO_ERROR;
+}
+
+void Loader::init_api(void* dso, 
+        char const * const * api, 
+        __eglMustCastToProperFunctionPointerType* curr, 
+        getProcAddressType getProcAddress) 
+{
+    char scrap[256];
+    while (*api) {
+        char const * name = *api;
+        __eglMustCastToProperFunctionPointerType f = 
+            (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
+        if (f == NULL) {
+            // couldn't find the entry-point, use eglGetProcAddress()
+            f = getProcAddress(name);
+        }
+        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"))) {
+                strncpy(scrap, name, index);
+                scrap[index] = 0;
+                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
+                //LOGD_IF(f, "found <%s> instead", scrap);
+            }
+        }
+        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");
+                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
+                //LOGD_IF(f, "found <%s> instead", scrap);
+            }
+        }
+        if (f == NULL) {
+            //LOGD("%s", name);
+            f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
+        }
+        *curr++ = f;
+        api++;
+    }
+}
+
+void *Loader::load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask)
+{
+    //LOGD("%s", driver);
+    void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL);
+    LOGE_IF(!dso, "%s", dlerror());
+    if (dso == 0)
+        return 0;
+
+    if (mask & EGL) {
+        getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
+
+        LOGE_IF(!getProcAddress, 
+                "can't find eglGetProcAddress() in %s", driver);        
+
+        gl_hooks_t::egl_t* egl = &hooks->egl;
+        __eglMustCastToProperFunctionPointerType* curr =
+            (__eglMustCastToProperFunctionPointerType*)egl;
+        char const * const * api = egl_names;
+        while (*api) {
+            char const * name = *api;
+            __eglMustCastToProperFunctionPointerType f = 
+                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
+            if (f == NULL) {
+                // couldn't find the entry-point, use eglGetProcAddress()
+                f = getProcAddress(name);
+                if (f == NULL) {
+                    f = (__eglMustCastToProperFunctionPointerType)0;
+                }
+            }
+            *curr++ = f;
+            api++;
+        }
+    }
+    
+    if (mask & GLESv1_CM) {
+        init_api(dso, gl_names,  
+                (__eglMustCastToProperFunctionPointerType*)&hooks->gl, 
+                getProcAddress);
+    }
+
+    if (mask & GLESv2) {
+      init_api(dso, gl2_names, 
+            (__eglMustCastToProperFunctionPointerType*)&hooks->gl2, 
+            getProcAddress);
+    }
+    
+    return dso;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
new file mode 100644
index 0000000..69f6dd5
--- /dev/null
+++ b/opengl/libs/EGL/Loader.h
@@ -0,0 +1,90 @@
+/* 
+ ** 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.
+ */
+
+#ifndef ANDROID_EGL_LOADER_H
+#define ANDROID_EGL_LOADER_H
+
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <EGL/egl.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+struct gl_hooks_t;
+
+class Loader : public Singleton<Loader>
+{
+    friend class Singleton<Loader>;
+
+    typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)(
+            const char*);
+   
+    enum {
+        EGL         = 0x01,
+        GLESv1_CM   = 0x02,
+        GLESv2      = 0x04
+    };
+    struct driver_t {
+        driver_t(void* gles);
+        ~driver_t();
+        status_t set(void* hnd, int32_t api);
+        void* dso[3];
+    };
+    
+    struct entry_t {
+        entry_t() { }
+        entry_t(int dpy, int impl, const char* tag);
+        int dpy;
+        int impl;
+        String8 tag;
+    };
+
+    Vector<entry_t> gConfig;    
+    getProcAddressType getProcAddress;
+    
+    const char* getTag(int dpy, int impl);
+
+public:
+    ~Loader();
+    
+    void* open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks);
+    status_t close(void* driver);
+    
+private:
+    Loader();
+    void *load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask);
+
+    static __attribute__((noinline))
+    void init_api(void* dso, 
+            char const * const * api, 
+            __eglMustCastToProperFunctionPointerType* curr, 
+            getProcAddressType getProcAddress); 
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif /* ANDROID_EGL_LOADER_H */
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 25e31ee..77648f2 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -14,9 +14,8 @@
  ** limitations under the License.
  */
 
-#define LOG_TAG "libEGL"
-
 #include <ctype.h>
+#include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <dlfcn.h>
@@ -37,11 +36,9 @@
 #include <cutils/properties.h>
 #include <cutils/memory.h>
 
-#include <utils/RefBase.h>
-
 #include "hooks.h"
 #include "egl_impl.h"
-
+#include "Loader.h"
 
 #define MAKE_CONFIG(_impl, _index)  ((EGLConfig)(((_impl)<<24) | (_index)))
 #define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
@@ -55,7 +52,15 @@
 static char const * const gVendorString     = "Android";
 static char const * const gVersionString    = "1.31 Android META-EGL";
 static char const * const gClientApiString  = "OpenGL ES";
-static char const * const gExtensionString  = "";
+static char const * const gExtensionString  = 
+        "EGL_KHR_image "
+        "EGL_KHR_image_base "
+        "EGL_KHR_image_pixmap "
+        "EGL_ANDROID_image_native_buffer "
+        "EGL_ANDROID_swap_rectangle "
+        ;
+
+// ----------------------------------------------------------------------------
 
 template <int MAGIC>
 struct egl_object_t
@@ -87,21 +92,15 @@
 struct egl_surface_t : public egl_object_t<'_srf'>
 {
     egl_surface_t(EGLDisplay dpy, EGLSurface surface,
-            NativeWindowType window, int impl, egl_connection_t const* cnx) 
-    : dpy(dpy), surface(surface), window(window), impl(impl), cnx(cnx)
+            int impl, egl_connection_t const* cnx) 
+    : dpy(dpy), surface(surface), impl(impl), cnx(cnx)
     {
         // NOTE: window must be incRef'ed and connected already
     }
     ~egl_surface_t() {
-        if (window) {
-            if (window->disconnect)
-                window->disconnect(window);
-            window->decRef(window);
-        }
     }
     EGLDisplay                  dpy;
     EGLSurface                  surface;
-    NativeWindowType            window;
     int                         impl;
     egl_connection_t const*     cnx;
 };
@@ -121,6 +120,18 @@
     egl_connection_t const*     cnx;
 };
 
+struct egl_image_t : public egl_object_t<'_img'>
+{
+    egl_image_t(EGLDisplay dpy, EGLContext context)
+        : dpy(dpy), context(context)
+    {
+        memset(images, 0, sizeof(images));
+    }
+    EGLDisplay dpy;
+    EGLConfig context;
+    EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+};
+
 struct tls_t
 {
     tls_t() : error(EGL_SUCCESS), ctx(0) { }
@@ -128,32 +139,6 @@
     EGLContext  ctx;
 };
 
-static 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,
-
-static char const * const gl_names[] = {
-    #include "gl_entries.in"
-    #include "glext_entries.in"
-    NULL
-};
-
-static char const * const egl_names[] = {
-    #include "egl_entries.in"
-    NULL
-};
-
-#undef GL_ENTRY
-#undef EGL_ENTRY
 
 // ----------------------------------------------------------------------------
 
@@ -262,110 +247,8 @@
     return tls->ctx;
 }
 
-
 /*****************************************************************************/
 
-class ISurfaceComposer;
-const sp<ISurfaceComposer>& getSurfaceFlinger();
-request_gpu_t* gpu_acquire(void* user);
-int gpu_release(void*, request_gpu_t* gpu);
-
-static __attribute__((noinline))
-void *load_driver(const char* driver, gl_hooks_t* hooks)
-{
-    //LOGD("%s", driver);
-    char scrap[256];
-    void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL);
-    LOGE_IF(!dso,
-            "couldn't load <%s> library (%s)",
-            driver, dlerror());
-
-    if (dso) {
-        // first find the symbol for eglGetProcAddress
-        
-        typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)(
-                const char*);
-        
-        getProcAddressType getProcAddress = 
-            (getProcAddressType)dlsym(dso, "eglGetProcAddress");
-        
-        LOGE_IF(!getProcAddress, 
-                "can't find eglGetProcAddress() in %s", driver);        
-        
-        __eglMustCastToProperFunctionPointerType* curr;
-        char const * const * api;
-
-        gl_hooks_t::egl_t* egl = &hooks->egl;
-        curr = (__eglMustCastToProperFunctionPointerType*)egl;
-        api = egl_names;
-        while (*api) {
-            char const * name = *api;
-            __eglMustCastToProperFunctionPointerType f = 
-                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
-            if (f == NULL) {
-                // couldn't find the entry-point, use eglGetProcAddress()
-                f = getProcAddress(name);
-                if (f == NULL) {
-                    f = (__eglMustCastToProperFunctionPointerType)0;
-                }
-            }
-            *curr++ = f;
-            api++;
-        }
-
-        gl_hooks_t::gl_t* gl = &hooks->gl;
-        curr = (__eglMustCastToProperFunctionPointerType*)gl;
-        api = gl_names;
-        while (*api) {
-            char const * name = *api;
-            __eglMustCastToProperFunctionPointerType f = 
-                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
-            if (f == NULL) {
-                // couldn't find the entry-point, use eglGetProcAddress()
-                f = getProcAddress(name);
-            }
-            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"))) {
-                    strncpy(scrap, name, index);
-                    scrap[index] = 0;
-                    f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
-                    //LOGD_IF(f, "found <%s> instead", scrap);
-                }
-            }
-            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");
-                    f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
-                    //LOGD_IF(f, "found <%s> instead", scrap);
-                }
-            }
-            if (f == NULL) {
-                //LOGD("%s", name);
-                f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
-            }
-            *curr++ = f;
-            api++;
-        }
-
-        // hook this driver up with surfaceflinger if needed
-        register_gpu_t register_gpu = 
-            (register_gpu_t)dlsym(dso, "oem_register_gpu");
-
-        if (register_gpu != NULL) {
-            if (getSurfaceFlinger() != 0) {
-                register_gpu(dso, gpu_acquire, gpu_release);
-            }
-        }
-    }
-    return dso;
-}
-
 template<typename T>
 static __attribute__((noinline))
 int binarySearch(
@@ -412,6 +295,14 @@
 };
 
 static const extention_map_t gExtentionMap[] = {
+    { "eglLockSurfaceKHR",  
+            (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 
+    { "eglUnlockSurfaceKHR", 
+            (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 
+    { "eglCreateImageKHR",  
+            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 
+    { "eglDestroyImageKHR", 
+            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 
 };
 
 static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS];
@@ -429,6 +320,12 @@
 
 // ----------------------------------------------------------------------------
 
+/*
+ * To "loose" the GPU, use something like
+ *    gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST];
+ * 
+ */
+
 static int gl_context_lost() {
     setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
     return 0;
@@ -491,6 +388,11 @@
     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 egl_connection_t* validate_display_config(
         EGLDisplay dpy, EGLConfig config,
         egl_display_t const*& dp, int& impl, int& index)
@@ -540,6 +442,24 @@
 }
 
 
+EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
+{
+    EGLContext context = 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->isValid())
+        return EGL_NO_IMAGE_KHR;
+
+    egl_image_t const * const i = get_image(image);
+    if (!i->isValid())
+        return EGL_NO_IMAGE_KHR;
+
+    return i->images[c->impl];
+}
+
+
 EGLDisplay egl_init_displays(NativeDisplayType display)
 {
     if (sEarlyInitState) {
@@ -554,12 +474,15 @@
     EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
     egl_display_t* d = &gDisplay[index];
 
+    // get our driver loader
+    Loader& loader(Loader::getInstance());    
+    
     // dynamically load all our EGL implementations for that display
     // and call into the real eglGetGisplay()
     egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
     if (cnx->dso == 0) {
         cnx->hooks = &gHooks[IMPL_SOFTWARE];
-        cnx->dso = load_driver("libagl.so", cnx->hooks);
+        cnx->dso = loader.open(display, 0, cnx->hooks);
     }
     if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) {
         d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display);
@@ -573,7 +496,7 @@
         property_get("debug.egl.hw", value, "1");
         if (atoi(value) != 0) {
             cnx->hooks = &gHooks[IMPL_HARDWARE];
-            cnx->dso = load_driver("libhgl.so", cnx->hooks);
+            cnx->dso = loader.open(display, 1, cnx->hooks);
         } else {
             LOGD("3D hardware acceleration is disabled");
         }
@@ -605,7 +528,8 @@
         if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) {
             LOGE("h/w accelerated eglGetDisplay() failed (%s)",
                     egl_strerror(cnx->hooks->egl.eglGetError()));
-            dlclose((void*)cnx->dso);
+            
+            loader.close(cnx->dso);
             cnx->dso = 0;
             // in case of failure, we want to make sure we don't try again
             // as it's expensive.
@@ -717,6 +641,8 @@
     if (android_atomic_dec(&dp->refs) != 1)
         return EGL_TRUE;
         
+    Loader& loader(Loader::getInstance());    
+
     EGLBoolean res = EGL_FALSE;
     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
@@ -732,7 +658,8 @@
             free((void*)dp->queryString[i].extensions);
             dp->numConfigs[i] = 0;
             dp->dpys[i] = EGL_NO_DISPLAY;
-            dlclose((void*)cnx->dso);
+
+            loader.close(cnx->dso);
             cnx->dso = 0;
             res = EGL_TRUE;
         }
@@ -909,26 +836,12 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        // window must be connected upon calling underlying
-        // eglCreateWindowSurface
-        if (window) {
-            window->incRef(window);
-            if (window->connect)
-                window->connect(window);
-        }
-
         EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface(
                 dp->dpys[i], dp->configs[i][index], window, attrib_list);       
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, window, i, cnx);
+            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
         }
-        
-        // something went wrong, disconnect and free window
-        // (will disconnect() automatically)
-        if (window) {
-            window->decRef(window);
-        }        
     }
     return EGL_NO_SURFACE;
 }
@@ -944,7 +857,7 @@
         EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface(
                 dp->dpys[i], dp->configs[i][index], pixmap, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx);
+            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
         }
     }
@@ -961,7 +874,7 @@
         EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface(
                 dp->dpys[i], dp->configs[i][index], attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx);
+            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
         }
     }
@@ -1428,3 +1341,144 @@
     }
     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
 }
+
+// ----------------------------------------------------------------------------
+// EGL_EGLEXT_VERSION 3
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+        const EGLint *attrib_list)
+{
+    EGLBoolean result = EGL_FALSE;
+    if (!validate_display_surface(dpy, surface))
+        return result;
+
+    egl_display_t const * const dp = get_display(dpy);
+    egl_surface_t const * const s = get_surface(surface);
+
+    if (s->cnx->hooks->egl.eglLockSurfaceKHR) {
+        result = s->cnx->hooks->egl.eglLockSurfaceKHR(
+                dp->dpys[s->impl], s->surface, attrib_list);
+    }
+    return result;
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+{
+    EGLBoolean result = EGL_FALSE;
+    if (!validate_display_surface(dpy, surface))
+        return result;
+
+    egl_display_t const * const dp = get_display(dpy);
+    egl_surface_t const * const s = get_surface(surface);
+
+    if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) {
+        result = s->cnx->hooks->egl.eglUnlockSurfaceKHR(
+                dp->dpys[s->impl], s->surface);
+    }
+    return result;
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+        EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+    if (ctx != EGL_NO_CONTEXT) {
+        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->hooks->egl.eglCreateImageKHR(
+                dp->dpys[c->impl], 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
+
+        EGLImageKHR implImages[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+        bool success = false;
+        for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+            egl_connection_t* const cnx = &gEGLImpl[i];
+            implImages[i] = EGL_NO_IMAGE_KHR;
+            if (cnx->dso) {
+                if (cnx->hooks->egl.eglCreateImageKHR) {
+                    implImages[i] = cnx->hooks->egl.eglCreateImageKHR(
+                            dp->dpys[i], ctx, target, buffer, attrib_list);
+                    if (implImages[i] != EGL_NO_IMAGE_KHR) {
+                        success = true;
+                    }
+                }
+            }
+        }
+        if (!success)
+            return EGL_NO_IMAGE_KHR;
+        
+        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)
+{
+     egl_display_t const * const dp = get_display(dpy);
+     if (dp == 0) {
+         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+     }
+
+     egl_image_t* image = get_image(img);
+     if (!image->isValid()) {
+         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+     }
+
+     bool success = false;
+     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+         egl_connection_t* const cnx = &gEGLImpl[i];
+         if (image->images[i] != EGL_NO_IMAGE_KHR) {
+             if (cnx->dso) {
+                 if (cnx->hooks->egl.eglCreateImageKHR) {
+                     if (cnx->hooks->egl.eglDestroyImageKHR(
+                             dp->dpys[i], image->images[i])) {
+                         success = true;
+                     }
+                 }
+             }
+         }
+     }
+     if (!success)
+         return EGL_FALSE;
+
+     delete image;
+
+     return EGL_FALSE;
+}
+
+
+// ----------------------------------------------------------------------------
+// ANDROID extensions
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
+        EGLint left, EGLint top, EGLint width, EGLint height)
+{
+    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->hooks->egl.eglSetSwapRectangleANDROID) {
+        return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(dp->dpys[s->impl],
+                s->surface, left, top, width, height);
+    }
+    return EGL_FALSE;
+}
+
diff --git a/opengl/libs/egl_entries.in b/opengl/libs/EGL/egl_entries.in
similarity index 95%
rename from opengl/libs/egl_entries.in
rename to opengl/libs/EGL/egl_entries.in
index 3b4551b..1fe2b57 100644
--- a/opengl/libs/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -50,3 +50,7 @@
 EGL_ENTRY(EGLBoolean,  eglUnlockSurfaceKHR, EGLDisplay, EGLSurface)
 EGL_ENTRY(EGLImageKHR, eglCreateImageKHR,   EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *)
 EGL_ENTRY(EGLBoolean,  eglDestroyImageKHR,  EGLDisplay, EGLImageKHR)
+
+/* ANDROID extensions */
+
+EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint)
diff --git a/opengl/libs/EGL/gpu.cpp b/opengl/libs/EGL/gpu.cpp
deleted file mode 100644
index 416bd5d..0000000
--- a/opengl/libs/EGL/gpu.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/* 
- ** Copyright 2007, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License"); 
- ** you may not use this file except in compliance with the License. 
- ** You may obtain a copy of the License at 
- **
- **     http://www.apache.org/licenses/LICENSE-2.0 
- **
- ** Unless required by applicable law or agreed to in writing, software 
- ** distributed under the License is distributed on an "AS IS" BASIS, 
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- ** See the License for the specific language governing permissions and 
- ** limitations under the License.
- */
-
-#define LOG_TAG "EGL"
-
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-
-#include <sys/ioctl.h>
-
-#if HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
-
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
-#include <binder/IMemory.h>
-#include <utils/threads.h>
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <binder/Parcel.h>
-
-#include <ui/EGLDisplaySurface.h>
-#include <ui/ISurfaceComposer.h>
-
-#include "hooks.h"
-#include "egl_impl.h"
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-/*
- * we provide our own allocators for the GPU regions, these
- * allocators go through surfaceflinger 
- */
-
-static Mutex                            gRegionsLock;
-static request_gpu_t                    gRegions;
-static sp<ISurfaceComposer>             gSurfaceManager;
-GL_API ISurfaceComposer*                GLES_localSurfaceManager = 0;
-
-extern egl_connection_t gEGLImpl[2];
-
-const sp<ISurfaceComposer>& getSurfaceFlinger()
-{
-    Mutex::Autolock _l(gRegionsLock);
-
-    /*
-     * There is a little bit of voodoo magic here. We want to access
-     * surfaceflinger for allocating GPU regions, however, when we are
-     * running as part of surfaceflinger, we want to bypass the
-     * service manager because surfaceflinger might not be registered yet.
-     * SurfaceFlinger will populate "GLES_localSurfaceManager" with its
-     * own address, so we can just use that.
-     */
-    if (gSurfaceManager == 0) {
-        if (GLES_localSurfaceManager) {
-            // we're running in SurfaceFlinger's context
-            gSurfaceManager =  GLES_localSurfaceManager;
-        } else {
-            // we're a remote process or not part of surfaceflinger,
-            // go through the service manager
-            sp<IServiceManager> sm = defaultServiceManager();
-            if (sm != NULL) {
-                sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
-                gSurfaceManager = interface_cast<ISurfaceComposer>(binder);
-            }
-        }
-    }
-    return gSurfaceManager;
-}
-
-class GPURevokeRequester : public BnGPUCallback
-{
-public:
-    virtual void gpuLost() {
-        LOGD("CONTEXT_LOST: Releasing GPU upon request from SurfaceFlinger.");
-        gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST];
-    }
-};
-
-static sp<GPURevokeRequester> gRevokerCallback;
-
-
-request_gpu_t* gpu_acquire(void* user)
-{
-    sp<ISurfaceComposer> server( getSurfaceFlinger() );
-
-    Mutex::Autolock _l(gRegionsLock);
-    if (server == NULL) {
-        return 0;
-    }
-    
-    ISurfaceComposer::gpu_info_t info;
-    
-    if (gRevokerCallback == 0)
-        gRevokerCallback = new GPURevokeRequester();
-
-    status_t err = server->requestGPU(gRevokerCallback, &info);
-    if (err != NO_ERROR) {
-        LOGD("requestGPU returned %d", err);
-        return 0;
-    }
-
-    if (info.regs == 0) {
-        LOGD("requestGPU() failed");
-        return 0;
-    }
-
-    bool failed = false;
-    request_gpu_t* gpu = &gRegions;
-    memset(gpu, 0, sizeof(*gpu));
-    
-    if (info.regs != 0) {
-        sp<IMemoryHeap> heap(info.regs->getMemory());
-        if (heap != 0) {
-            int fd = heap->heapID();
-            gpu->regs.fd = fd;
-            gpu->regs.base = info.regs->pointer(); 
-            gpu->regs.size = info.regs->size(); 
-            gpu->regs.user = info.regs.get();
-#if HAVE_ANDROID_OS
-            struct pmem_region region;
-            if (ioctl(fd, PMEM_GET_PHYS, &region) >= 0)
-                gpu->regs.phys = (void*)region.offset;
-#endif
-            info.regs->incStrong(gpu);
-        } else {
-            LOGE("GPU register handle %p is invalid!", info.regs.get());
-            failed = true;
-        }
-    }
-
-    for (size_t i=0 ; i<info.count && !failed ; i++) {
-        sp<IMemory>& region(info.regions[i].region);
-        if (region != 0) {
-            sp<IMemoryHeap> heap(region->getMemory());
-            if (heap != 0) {
-                const int fd = heap->heapID();
-                gpu->gpu[i].fd = fd;
-                gpu->gpu[i].base = region->pointer(); 
-                gpu->gpu[i].size = region->size(); 
-                gpu->gpu[i].user = region.get();
-                gpu->gpu[i].offset = info.regions[i].reserved;
-#if HAVE_ANDROID_OS
-                struct pmem_region reg;
-                if (ioctl(fd, PMEM_GET_PHYS, &reg) >= 0)
-                    gpu->gpu[i].phys = (void*)reg.offset;
-#endif
-                region->incStrong(gpu);
-            } else {
-                LOGE("GPU region handle [%d, %p] is invalid!", i, region.get());
-                failed = true;
-            }
-        }
-    }
-    
-    if (failed) {
-        // something went wrong, clean up everything!
-        if (gpu->regs.user) {
-            static_cast<IMemory*>(gpu->regs.user)->decStrong(gpu);
-            for (size_t i=0 ; i<info.count ; i++) {
-                if (gpu->gpu[i].user) {
-                    static_cast<IMemory*>(gpu->gpu[i].user)->decStrong(gpu);
-                }
-            }
-        }
-    }
-    
-    gpu->count = info.count;
-    return gpu;
-}
-
-int gpu_release(void*, request_gpu_t* gpu)
-{
-    sp<IMemory> regs;
-
-    { // scope for lock
-        Mutex::Autolock _l(gRegionsLock);
-        regs = static_cast<IMemory*>(gpu->regs.user);   
-        gpu->regs.user = 0;
-        if (regs != 0) regs->decStrong(gpu);
-        
-        for (int i=0 ; i<gpu->count ; i++) {
-            sp<IMemory> r(static_cast<IMemory*>(gpu->gpu[i].user));
-            gpu->gpu[i].user = 0;
-            if (r != 0) r->decStrong(gpu);
-        }
-    }
-    
-    // there is a special transaction to relinquish the GPU
-    // (it will happen automatically anyway if we don't do this)
-    Parcel data, reply;
-    // NOTE: this transaction does not require an interface token
-    regs->asBinder()->transact(1000, data, &reply);
-    return 1;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/hooks.cpp b/opengl/libs/EGL/hooks.cpp
new file mode 100644
index 0000000..2246366
--- /dev/null
+++ b/opengl/libs/EGL/hooks.cpp
@@ -0,0 +1,67 @@
+/* 
+ ** 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 "GLES_CM/gl_entries.in"
+    #include "GLES_CM/glext_entries.in"
+    NULL
+};
+
+char const * const gl2_names[] = {
+    #include "GLES2/gl2_entries.in"
+    #include "GLES2/gl2ext_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/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
new file mode 100644
index 0000000..e5358c3
--- /dev/null
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -0,0 +1,111 @@
+/* 
+ ** 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 <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include "hooks.h"
+#include "egl_impl.h"
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+// Actual GL entry-points
+// ----------------------------------------------------------------------------
+
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
+
+#if USE_FAST_TLS_KEY
+
+    #define API_ENTRY(_api) __attribute__((naked)) _api
+
+    #define CALL_GL_API(_api, ...)                              \
+         asm volatile(                                          \
+            "mov   r12, #0xFFFF0FFF   \n"                       \
+            "ldr   r12, [r12, #-15]   \n"                       \
+            "ldr   r12, [r12, %[tls]] \n"                       \
+            "cmp   r12, #0            \n"                       \
+            "ldrne pc,  [r12, %[api]] \n"                       \
+            "bx    lr                 \n"                       \
+            :                                                   \
+            : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
+              [api] "J"(__builtin_offsetof(gl_hooks_t, gl2._api))    \
+            :                                                   \
+            );
+    
+    #define CALL_GL_API_RETURN(_api, ...) \
+        CALL_GL_API(_api, __VA_ARGS__) \
+        return 0; // placate gcc's warnings. never reached.
+
+#else
+
+    #define API_ENTRY(_api) _api
+
+    #define CALL_GL_API(_api, ...)                                       \
+        gl_hooks_t::gl2_t const * const _c = &getGlThreadSpecific()->gl2; \
+        _c->_api(__VA_ARGS__)
+    
+    #define CALL_GL_API_RETURN(_api, ...)                                \
+        gl_hooks_t::gl2_t const * const _c = &getGlThreadSpecific()->gl2; \
+        return _c->_api(__VA_ARGS__)
+
+#endif
+
+
+extern "C" {
+#include "gl2_api.in"
+#include "gl2ext_api.in"
+}
+
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
+
+
+/*
+ * These GL calls are special because they need to EGL to retrieve some
+ * informations before they can execute.
+ */
+
+extern "C" void __glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+extern "C" void __glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
+
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage = 
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    __glEGLImageTargetTexture2DOES(target, implImage);
+}
+
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage = 
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    __glEGLImageTargetRenderbufferStorageOES(target, image);
+}
+
diff --git a/opengl/libs/GLES2/gl2_api.in b/opengl/libs/GLES2/gl2_api.in
new file mode 100644
index 0000000..9c2e69a
--- /dev/null
+++ b/opengl/libs/GLES2/gl2_api.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 char* 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 void* data, GLenum usage) {
+    CALL_GL_API(glBufferData, target, size, data, usage);
+}
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
+    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 void* data) {
+    CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
+    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* buffers) {
+    CALL_GL_API(glDeleteBuffers, n, buffers);
+}
+void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers) {
+    CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glDeleteProgram)(GLuint program) {
+    CALL_GL_API(glDeleteProgram, program);
+}
+void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers) {
+    CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glDeleteShader)(GLuint shader) {
+    CALL_GL_API(glDeleteShader, shader);
+}
+void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint* textures) {
+    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 void* 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* buffers) {
+    CALL_GL_API(glGenBuffers, n, buffers);
+}
+void API_ENTRY(glGenerateMipmap)(GLenum target) {
+    CALL_GL_API(glGenerateMipmap, target);
+}
+void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint* framebuffers) {
+    CALL_GL_API(glGenFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers) {
+    CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint* textures) {
+    CALL_GL_API(glGenTextures, n, textures);
+}
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* 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, char* 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 char* 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* params) {
+    CALL_GL_API(glGetProgramiv, program, pname, params);
+}
+void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* 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* params) {
+    CALL_GL_API(glGetShaderiv, shader, pname, params);
+}
+void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* 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, char* 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 char* 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, void** 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, void* 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 void* binary, GLsizei length) {
+    CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length);
+}
+void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const char** 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 void* 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* 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* 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* 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(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* 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(glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* 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* 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* 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* 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* values) {
+    CALL_GL_API(glVertexAttrib4fv, indx, values);
+}
+void API_ENTRY(glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* 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/gl2_entries.in b/opengl/libs/GLES2/gl2_entries.in
new file mode 100644
index 0000000..6a41b94
--- /dev/null
+++ b/opengl/libs/GLES2/gl2_entries.in
@@ -0,0 +1,142 @@
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const char* name)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glBlendEquation,  GLenum mode )
+GL_ENTRY(void, glBlendEquationSeparate, 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, glBufferData, GLenum target, GLsizeiptr size, const void* data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void* data)
+GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glClearDepthf, GLclampf depth)
+GL_ENTRY(void, glClearStencil, GLint s)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glCompileShader, GLuint shader)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* 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(GLuint, glCreateProgram, void)
+GL_ENTRY(GLuint, glCreateShader, GLenum type)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint* buffers)
+GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeleteProgram, GLuint program)
+GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteShader, GLuint shader)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint* textures)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void* indices)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFramebufferRenderbuffer, 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, glFrontFace, GLenum mode)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint* buffers)
+GL_ENTRY(void, glGenerateMipmap, GLenum target)
+GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint* textures)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+GL_ENTRY(int, glGetAttribLocation, GLuint program, const char* name)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean* params)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat* params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+GL_ENTRY(const GLubyte*, glGetString, GLenum name)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat* params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
+GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
+GL_ENTRY(int, glGetUniformLocation, GLuint program, const char* name)
+GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
+GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsProgram, GLuint program)
+GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsShader, GLuint shader)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLinkProgram, GLuint program)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
+GL_ENTRY(void, glReleaseShaderCompiler, void)
+GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const char** string, const GLint* length)
+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(void, glTexImage2D, GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, 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, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels)
+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(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 void* ptr)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
diff --git a/opengl/libs/GLES2/gl2ext_api.in b/opengl/libs/GLES2/gl2ext_api.in
new file mode 100644
index 0000000..6eeecb3
--- /dev/null
+++ b/opengl/libs/GLES2/gl2ext_api.in
@@ -0,0 +1,105 @@
+void API_ENTRY(__glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) {
+    CALL_GL_API(glEGLImageTargetTexture2DOES, target, image);
+}
+void API_ENTRY(__glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image) {
+    CALL_GL_API(glEGLImageTargetRenderbufferStorageOES, target, image);
+}
+void API_ENTRY(glGetProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) {
+    CALL_GL_API(glGetProgramBinaryOES, program, bufSize, length, binaryFormat, binary);
+}
+void API_ENTRY(glProgramBinaryOES)(GLuint program, GLenum binaryFormat, const void *binary, GLint length) {
+    CALL_GL_API(glProgramBinaryOES, program, binaryFormat, binary, length);
+}
+void* API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) {
+    CALL_GL_API_RETURN(glMapBufferOES, target, access);
+}
+GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) {
+    CALL_GL_API_RETURN(glUnmapBufferOES, target);
+}
+void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void** params) {
+    CALL_GL_API(glGetBufferPointervOES, target, pname, params);
+}
+void API_ENTRY(glTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) {
+    CALL_GL_API(glTexImage3DOES, target, level, internalformat, width, height, depth, border, format, type, pixels);
+}
+void API_ENTRY(glTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) {
+    CALL_GL_API(glTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+}
+void API_ENTRY(glCopyTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glCopyTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, x, y, width, height);
+}
+void API_ENTRY(glCompressedTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data) {
+    CALL_GL_API(glCompressedTexImage3DOES, target, level, internalformat, width, height, depth, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data) {
+    CALL_GL_API(glCompressedTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+}
+void API_ENTRY(glFramebufferTexture3DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
+    CALL_GL_API(glFramebufferTexture3DOES, target, attachment, textarget, texture, level, zoffset);
+}
+void API_ENTRY(glGetPerfMonitorGroupsAMD)(GLint *numGroups, GLsizei groupsSize, GLuint *groups) {
+    CALL_GL_API(glGetPerfMonitorGroupsAMD, numGroups, groupsSize, groups);
+}
+void API_ENTRY(glGetPerfMonitorCountersAMD)(GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters) {
+    CALL_GL_API(glGetPerfMonitorCountersAMD, group, numCounters, maxActiveCounters, counterSize, counters);
+}
+void API_ENTRY(glGetPerfMonitorGroupStringAMD)(GLuint group, GLsizei bufSize, GLsizei *length, char *groupString) {
+    CALL_GL_API(glGetPerfMonitorGroupStringAMD, group, bufSize, length, groupString);
+}
+void API_ENTRY(glGetPerfMonitorCounterStringAMD)(GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString) {
+    CALL_GL_API(glGetPerfMonitorCounterStringAMD, group, counter, bufSize, length, counterString);
+}
+void API_ENTRY(glGetPerfMonitorCounterInfoAMD)(GLuint group, GLuint counter, GLenum pname, void *data) {
+    CALL_GL_API(glGetPerfMonitorCounterInfoAMD, group, counter, pname, data);
+}
+void API_ENTRY(glGenPerfMonitorsAMD)(GLsizei n, GLuint *monitors) {
+    CALL_GL_API(glGenPerfMonitorsAMD, n, monitors);
+}
+void API_ENTRY(glDeletePerfMonitorsAMD)(GLsizei n, GLuint *monitors) {
+    CALL_GL_API(glDeletePerfMonitorsAMD, n, monitors);
+}
+void API_ENTRY(glSelectPerfMonitorCountersAMD)(GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList) {
+    CALL_GL_API(glSelectPerfMonitorCountersAMD, monitor, enable, group, numCounters, countersList);
+}
+void API_ENTRY(glBeginPerfMonitorAMD)(GLuint monitor) {
+    CALL_GL_API(glBeginPerfMonitorAMD, monitor);
+}
+void API_ENTRY(glEndPerfMonitorAMD)(GLuint monitor) {
+    CALL_GL_API(glEndPerfMonitorAMD, monitor);
+}
+void API_ENTRY(glGetPerfMonitorCounterDataAMD)(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten) {
+    CALL_GL_API(glGetPerfMonitorCounterDataAMD, monitor, pname, dataSize, data, bytesWritten);
+}
+void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint *fences) {
+    CALL_GL_API(glDeleteFencesNV, n, fences);
+}
+void API_ENTRY(glGenFencesNV)(GLsizei n, GLuint *fences) {
+    CALL_GL_API(glGenFencesNV, n, fences);
+}
+GLboolean API_ENTRY(glIsFenceNV)(GLuint fence) {
+    CALL_GL_API_RETURN(glIsFenceNV, fence);
+}
+GLboolean API_ENTRY(glTestFenceNV)(GLuint fence) {
+    CALL_GL_API_RETURN(glTestFenceNV, fence);
+}
+void API_ENTRY(glGetFenceivNV)(GLuint fence, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetFenceivNV, fence, pname, params);
+}
+void API_ENTRY(glFinishFenceNV)(GLuint fence) {
+    CALL_GL_API(glFinishFenceNV, fence);
+}
+void API_ENTRY(glSetFenceNV)(GLuint fence, GLenum condition) {
+    CALL_GL_API(glSetFenceNV, fence, condition);
+}
+void API_ENTRY(glGetDriverControlsQCOM)(GLint *num, GLsizei size, GLuint *driverControls) {
+    CALL_GL_API(glGetDriverControlsQCOM, num, size, driverControls);
+}
+void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString) {
+    CALL_GL_API(glGetDriverControlStringQCOM, driverControl, bufSize, length, driverControlString);
+}
+void API_ENTRY(glEnableDriverControlQCOM)(GLuint driverControl) {
+    CALL_GL_API(glEnableDriverControlQCOM, driverControl);
+}
+void API_ENTRY(glDisableDriverControlQCOM)(GLuint driverControl) {
+    CALL_GL_API(glDisableDriverControlQCOM, driverControl);
+}
diff --git a/opengl/libs/GLES2/gl2ext_entries.in b/opengl/libs/GLES2/gl2ext_entries.in
new file mode 100644
index 0000000..e608f5d
--- /dev/null
+++ b/opengl/libs/GLES2/gl2ext_entries.in
@@ -0,0 +1,35 @@
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
+GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
+GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, char *groupString)
+GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString)
+GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data)
+GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
+GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
+GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
+GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
+GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
+GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
+GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
+GL_ENTRY(void, glFinishFenceNV, GLuint fence)
+GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
+GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString)
+GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 384b59a..3204d9a 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -14,8 +14,6 @@
  ** limitations under the License.
  */
 
-#define LOG_TAG "GLES_CM"
-
 #include <ctype.h>
 #include <string.h>
 #include <errno.h>
@@ -121,16 +119,25 @@
 
 
 /*
- * These GL calls are special because they need to call into EGL to retrieve
- * some informations before they can execute.
+ * These GL calls are special because they need to EGL to retrieve some
+ * informations before they can execute.
  */
 
+extern "C" void __glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+extern "C" void __glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
+
 
 void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
 {
+    GLeglImageOES implImage = 
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    __glEGLImageTargetTexture2DOES(target, implImage);
 }
 
 void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
 {
+    GLeglImageOES implImage = 
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    __glEGLImageTargetRenderbufferStorageOES(target, image);
 }
 
diff --git a/opengl/libs/gl_entries.in b/opengl/libs/GLES_CM/gl_entries.in
similarity index 100%
rename from opengl/libs/gl_entries.in
rename to opengl/libs/GLES_CM/gl_entries.in
diff --git a/opengl/libs/glext_entries.in b/opengl/libs/GLES_CM/glext_entries.in
similarity index 100%
rename from opengl/libs/glext_entries.in
rename to opengl/libs/GLES_CM/glext_entries.in
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index 312b176..c5f753d 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -31,13 +31,15 @@
 
 struct egl_connection_t
 {
-    void volatile *     dso;
+    void *              dso;
     gl_hooks_t *        hooks;
     EGLint              major;
     EGLint              minor;
     int                 unavailable;
 };
 
+EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/gl_enums.in b/opengl/libs/gl_enums.in
deleted file mode 100644
index ffc2fad..0000000
--- a/opengl/libs/gl_enums.in
+++ /dev/null
@@ -1,261 +0,0 @@
-GLENUM(GL_POINTS, 0x0000)
-GLENUM(GL_LINES, 0x0001)
-GLENUM(GL_LINE_LOOP, 0x0002)
-GLENUM(GL_LINE_STRIP, 0x0003)
-GLENUM(GL_TRIANGLES, 0x0004)
-GLENUM(GL_TRIANGLE_STRIP, 0x0005)
-GLENUM(GL_TRIANGLE_FAN, 0x0006)
-GLENUM(GL_ADD, 0x0104)
-GLENUM(GL_NEVER, 0x0200)
-GLENUM(GL_LESS, 0x0201)
-GLENUM(GL_EQUAL, 0x0202)
-GLENUM(GL_LEQUAL, 0x0203)
-GLENUM(GL_GREATER, 0x0204)
-GLENUM(GL_NOTEQUAL, 0x0205)
-GLENUM(GL_GEQUAL, 0x0206)
-GLENUM(GL_ALWAYS, 0x0207)
-GLENUM(GL_SRC_COLOR, 0x0300)
-GLENUM(GL_ONE_MINUS_SRC_COLOR, 0x0301)
-GLENUM(GL_SRC_ALPHA, 0x0302)
-GLENUM(GL_ONE_MINUS_SRC_ALPHA, 0x0303)
-GLENUM(GL_DST_ALPHA, 0x0304)
-GLENUM(GL_ONE_MINUS_DST_ALPHA, 0x0305)
-GLENUM(GL_DST_COLOR, 0x0306)
-GLENUM(GL_ONE_MINUS_DST_COLOR, 0x0307)
-GLENUM(GL_SRC_ALPHA_SATURATE, 0x0308)
-GLENUM(GL_FRONT, 0x0404)
-GLENUM(GL_BACK, 0x0405)
-GLENUM(GL_FRONT_AND_BACK, 0x0408)
-GLENUM(GL_INVALID_ENUM, 0x0500)
-GLENUM(GL_INVALID_VALUE, 0x0501)
-GLENUM(GL_INVALID_OPERATION, 0x0502)
-GLENUM(GL_STACK_OVERFLOW, 0x0503)
-GLENUM(GL_STACK_UNDERFLOW, 0x0504)
-GLENUM(GL_OUT_OF_MEMORY, 0x0505)
-GLENUM(GL_EXP, 0x0800)
-GLENUM(GL_EXP2, 0x0801)
-GLENUM(GL_CW, 0x0900)
-GLENUM(GL_CCW, 0x0901)
-GLENUM(GL_POINT_SMOOTH, 0x0B10)
-GLENUM(GL_SMOOTH_POINT_SIZE_RANGE, 0x0B12)
-GLENUM(GL_LINE_SMOOTH, 0x0B20)
-GLENUM(GL_SMOOTH_LINE_WIDTH_RANGE, 0x0B22)
-GLENUM(GL_CULL_FACE, 0x0B44)
-GLENUM(GL_LIGHTING, 0x0B50)
-GLENUM(GL_LIGHT_MODEL_TWO_SIDE, 0x0B52)
-GLENUM(GL_LIGHT_MODEL_AMBIENT, 0x0B53)
-GLENUM(GL_COLOR_MATERIAL, 0x0B57)
-GLENUM(GL_FOG, 0x0B60)
-GLENUM(GL_FOG_DENSITY, 0x0B62)
-GLENUM(GL_FOG_START, 0x0B63)
-GLENUM(GL_FOG_END, 0x0B64)
-GLENUM(GL_FOG_MODE, 0x0B65)
-GLENUM(GL_FOG_COLOR, 0x0B66)
-GLENUM(GL_DEPTH_TEST, 0x0B71)
-GLENUM(GL_STENCIL_TEST, 0x0B90)
-GLENUM(GL_NORMALIZE, 0x0BA1)
-GLENUM(GL_ALPHA_TEST, 0x0BC0)
-GLENUM(GL_DITHER, 0x0BD0)
-GLENUM(GL_BLEND, 0x0BE2)
-GLENUM(GL_COLOR_LOGIC_OP, 0x0BF2)
-GLENUM(GL_SCISSOR_TEST, 0x0C11)
-GLENUM(GL_PERSPECTIVE_CORRECTION_HINT, 0x0C50)
-GLENUM(GL_POINT_SMOOTH_HINT, 0x0C51)
-GLENUM(GL_LINE_SMOOTH_HINT, 0x0C52)
-GLENUM(GL_POLYGON_SMOOTH_HINT, 0x0C53)
-GLENUM(GL_FOG_HINT, 0x0C54)
-GLENUM(GL_UNPACK_ALIGNMENT, 0x0CF5)
-GLENUM(GL_PACK_ALIGNMENT, 0x0D05)
-GLENUM(GL_MAX_LIGHTS, 0x0D31)
-GLENUM(GL_MAX_CLIP_PLANES, 0x0D32)
-GLENUM(GL_MAX_TEXTURE_SIZE, 0x0D33)
-GLENUM(GL_MAX_MODELVIEW_STACK_DEPTH, 0x0D36)
-GLENUM(GL_MAX_PROJECTION_STACK_DEPTH, 0x0D38)
-GLENUM(GL_MAX_TEXTURE_STACK_DEPTH, 0x0D39)
-GLENUM(GL_MAX_VIEWPORT_DIMS, 0x0D3A)
-GLENUM(GL_RED_BITS, 0x0D52)
-GLENUM(GL_GREEN_BITS, 0x0D53)
-GLENUM(GL_BLUE_BITS, 0x0D54)
-GLENUM(GL_ALPHA_BITS, 0x0D55)
-GLENUM(GL_DEPTH_BITS, 0x0D56)
-GLENUM(GL_STENCIL_BITS, 0x0D57)
-GLENUM(GL_TEXTURE_2D, 0x0DE1)
-GLENUM(GL_DONT_CARE, 0x1100)
-GLENUM(GL_FASTEST, 0x1101)
-GLENUM(GL_NICEST, 0x1102)
-GLENUM(GL_AMBIENT, 0x1200)
-GLENUM(GL_DIFFUSE, 0x1201)
-GLENUM(GL_SPECULAR, 0x1202)
-GLENUM(GL_POSITION, 0x1203)
-GLENUM(GL_SPOT_DIRECTION, 0x1204)
-GLENUM(GL_SPOT_EXPONENT, 0x1205)
-GLENUM(GL_SPOT_CUTOFF, 0x1206)
-GLENUM(GL_CONSTANT_ATTENUATION, 0x1207)
-GLENUM(GL_LINEAR_ATTENUATION, 0x1208)
-GLENUM(GL_QUADRATIC_ATTENUATION, 0x1209)
-GLENUM(GL_BYTE, 0x1400)
-GLENUM(GL_UNSIGNED_BYTE, 0x1401)
-GLENUM(GL_SHORT, 0x1402)
-GLENUM(GL_UNSIGNED_SHORT, 0x1403)
-GLENUM(GL_FLOAT, 0x1406)
-GLENUM(GL_FIXED, 0x140C)
-GLENUM(GL_CLEAR, 0x1500)
-GLENUM(GL_AND, 0x1501)
-GLENUM(GL_AND_REVERSE, 0x1502)
-GLENUM(GL_COPY, 0x1503)
-GLENUM(GL_AND_INVERTED, 0x1504)
-GLENUM(GL_NOOP, 0x1505)
-GLENUM(GL_XOR, 0x1506)
-GLENUM(GL_OR, 0x1507)
-GLENUM(GL_NOR, 0x1508)
-GLENUM(GL_EQUIV, 0x1509)
-GLENUM(GL_INVERT, 0x150A)
-GLENUM(GL_OR_REVERSE, 0x150B)
-GLENUM(GL_COPY_INVERTED, 0x150C)
-GLENUM(GL_OR_INVERTED, 0x150D)
-GLENUM(GL_NAND, 0x150E)
-GLENUM(GL_SET, 0x150F)
-GLENUM(GL_EMISSION, 0x1600)
-GLENUM(GL_SHININESS, 0x1601)
-GLENUM(GL_AMBIENT_AND_DIFFUSE, 0x1602)
-GLENUM(GL_MODELVIEW, 0x1700)
-GLENUM(GL_PROJECTION, 0x1701)
-GLENUM(GL_TEXTURE, 0x1702)
-GLENUM(GL_ALPHA, 0x1906)
-GLENUM(GL_RGB, 0x1907)
-GLENUM(GL_RGBA, 0x1908)
-GLENUM(GL_LUMINANCE, 0x1909)
-GLENUM(GL_LUMINANCE_ALPHA, 0x190A)
-GLENUM(GL_FLAT, 0x1D00)
-GLENUM(GL_SMOOTH, 0x1D01)
-GLENUM(GL_KEEP, 0x1E00)
-GLENUM(GL_REPLACE, 0x1E01)
-GLENUM(GL_REPLACE, 0x1E01)
-GLENUM(GL_INCR, 0x1E02)
-GLENUM(GL_DECR, 0x1E03)
-GLENUM(GL_VENDOR, 0x1F00)
-GLENUM(GL_RENDERER, 0x1F01)
-GLENUM(GL_VERSION, 0x1F02)
-GLENUM(GL_EXTENSIONS, 0x1F03)
-GLENUM(GL_MODULATE, 0x2100)
-GLENUM(GL_DECAL, 0x2101)
-GLENUM(GL_TEXTURE_ENV_MODE, 0x2200)
-GLENUM(GL_TEXTURE_ENV_COLOR, 0x2201)
-GLENUM(GL_TEXTURE_ENV, 0x2300)
-GLENUM(GL_NEAREST, 0x2600)
-GLENUM(GL_LINEAR, 0x2601)
-GLENUM(GL_NEAREST_MIPMAP_NEAREST, 0x2700)
-GLENUM(GL_LINEAR_MIPMAP_NEAREST, 0x2701)
-GLENUM(GL_NEAREST_MIPMAP_LINEAR, 0x2702)
-GLENUM(GL_LINEAR_MIPMAP_LINEAR, 0x2703)
-GLENUM(GL_TEXTURE_MAG_FILTER, 0x2800)
-GLENUM(GL_TEXTURE_MIN_FILTER, 0x2801)
-GLENUM(GL_TEXTURE_WRAP_S, 0x2802)
-GLENUM(GL_TEXTURE_WRAP_T, 0x2803)
-GLENUM(GL_CLAMP, 0x2900)
-GLENUM(GL_REPEAT, 0x2901)
-GLENUM(GL_CLIP_PLANE0, 0x3000)
-GLENUM(GL_CLIP_PLANE1, 0x3001)
-GLENUM(GL_CLIP_PLANE2, 0x3002)
-GLENUM(GL_CLIP_PLANE3, 0x3003)
-GLENUM(GL_CLIP_PLANE4, 0x3004)
-GLENUM(GL_CLIP_PLANE5, 0x3005)
-GLENUM(GL_LIGHT0, 0x4000)
-GLENUM(GL_LIGHT1, 0x4001)
-GLENUM(GL_LIGHT2, 0x4002)
-GLENUM(GL_LIGHT3, 0x4003)
-GLENUM(GL_LIGHT4, 0x4004)
-GLENUM(GL_LIGHT5, 0x4005)
-GLENUM(GL_LIGHT6, 0x4006)
-GLENUM(GL_LIGHT7, 0x4007)
-GLENUM(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0x7E80)
-GLENUM(GL_UNSIGNED_SHORT_4_4_4_4, 0x8033)
-GLENUM(GL_UNSIGNED_SHORT_5_5_5_1, 0x8034)
-GLENUM(GL_POLYGON_OFFSET_FILL, 0x8037)
-GLENUM(GL_RESCALE_NORMAL, 0x803A)
-GLENUM(GL_VERTEX_ARRAY, 0x8074)
-GLENUM(GL_NORMAL_ARRAY, 0x8075)
-GLENUM(GL_COLOR_ARRAY, 0x8076)
-GLENUM(GL_TEXTURE_COORD_ARRAY, 0x8078)
-GLENUM(GL_MULTISAMPLE, 0x809D)
-GLENUM(GL_SAMPLE_ALPHA_TO_COVERAGE, 0x809E)
-GLENUM(GL_SAMPLE_ALPHA_TO_ONE, 0x809F)
-GLENUM(GL_SAMPLE_COVERAGE, 0x80A0)
-GLENUM(GL_MAX_ELEMENTS_VERTICES, 0x80E8)
-GLENUM(GL_MAX_ELEMENTS_INDICES, 0x80E9)
-GLENUM(GL_CLAMP_TO_EDGE, 0x812F)
-GLENUM(GL_GENERATE_MIPMAP, 0x8191)
-GLENUM(GL_GENERATE_MIPMAP_HINT, 0x8192)
-GLENUM(GL_UNSIGNED_SHORT_5_6_5, 0x8363)
-GLENUM(GL_ALIASED_POINT_SIZE_RANGE, 0x846D)
-GLENUM(GL_ALIASED_LINE_WIDTH_RANGE, 0x846E)
-GLENUM(GL_TEXTURE0, 0x84C0)
-GLENUM(GL_TEXTURE1, 0x84C1)
-GLENUM(GL_TEXTURE2, 0x84C2)
-GLENUM(GL_TEXTURE3, 0x84C3)
-GLENUM(GL_TEXTURE4, 0x84C4)
-GLENUM(GL_TEXTURE5, 0x84C5)
-GLENUM(GL_TEXTURE6, 0x84C6)
-GLENUM(GL_TEXTURE7, 0x84C7)
-GLENUM(GL_TEXTURE8, 0x84C8)
-GLENUM(GL_TEXTURE9, 0x84C9)
-GLENUM(GL_TEXTURE10, 0x84CA)
-GLENUM(GL_TEXTURE11, 0x84CB)
-GLENUM(GL_TEXTURE12, 0x84CC)
-GLENUM(GL_TEXTURE13, 0x84CD)
-GLENUM(GL_TEXTURE14, 0x84CE)
-GLENUM(GL_TEXTURE15, 0x84CF)
-GLENUM(GL_TEXTURE16, 0x84D0)
-GLENUM(GL_TEXTURE17, 0x84D1)
-GLENUM(GL_TEXTURE18, 0x84D2)
-GLENUM(GL_TEXTURE19, 0x84D3)
-GLENUM(GL_TEXTURE20, 0x84D4)
-GLENUM(GL_TEXTURE21, 0x84D5)
-GLENUM(GL_TEXTURE22, 0x84D6)
-GLENUM(GL_TEXTURE23, 0x84D7)
-GLENUM(GL_TEXTURE24, 0x84D8)
-GLENUM(GL_TEXTURE25, 0x84D9)
-GLENUM(GL_TEXTURE26, 0x84DA)
-GLENUM(GL_TEXTURE27, 0x84DB)
-GLENUM(GL_TEXTURE28, 0x84DC)
-GLENUM(GL_TEXTURE29, 0x84DD)
-GLENUM(GL_TEXTURE30, 0x84DE)
-GLENUM(GL_TEXTURE31, 0x84DF)
-GLENUM(GL_MAX_TEXTURE_UNITS, 0x84E2)
-GLENUM(GL_NUM_COMPRESSED_TEXTURE_FORMATS, 0x86A2)
-GLENUM(GL_COMPRESSED_TEXTURE_FORMATS, 0x86A3)
-GLENUM(GL_BUFFER_SIZE, 0x8764)
-GLENUM(GL_BUFFER_USAGE, 0x8765)
-GLENUM(GL_POINT_SPRITE_OES, 0x8861)
-GLENUM(GL_COORD_REPLACE_OES, 0x8862)
-GLENUM(GL_ARRAY_BUFFER, 0x8892)
-GLENUM(GL_ELEMENT_ARRAY_BUFFER, 0x8893)
-GLENUM(GL_ARRAY_BUFFER_BINDING, 0x8894)
-GLENUM(GL_ELEMENT_ARRAY_BUFFER_BINDING, 0x8895)
-GLENUM(GL_VERTEX_ARRAY_BUFFER_BINDING, 0x8896)
-GLENUM(GL_NORMAL_ARRAY_BUFFER_BINDING, 0x8897)
-GLENUM(GL_COLOR_ARRAY_BUFFER_BINDING, 0x8898)
-GLENUM(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, 0x889A)
-GLENUM(GL_STATIC_DRAW, 0x88E4)
-GLENUM(GL_DYNAMIC_DRAW, 0x88E8)
-GLENUM(GL_POINT_SIZE_ARRAY_TYPE_OES, 0x898A)
-GLENUM(GL_POINT_SIZE_ARRAY_STRIDE_OES, 0x898B)
-GLENUM(GL_POINT_SIZE_ARRAY_POINTER_OES, 0x898C)
-GLENUM(GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898D)
-GLENUM(GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898E)
-GLENUM(GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898F)
-GLENUM(GL_PALETTE4_RGB8_OES, 0x8B90)
-GLENUM(GL_PALETTE4_RGBA8_OES, 0x8B91)
-GLENUM(GL_PALETTE4_R5_G6_B5_OES, 0x8B92)
-GLENUM(GL_PALETTE4_RGBA4_OES, 0x8B93)
-GLENUM(GL_PALETTE4_RGB5_A1_OES, 0x8B94)
-GLENUM(GL_PALETTE8_RGB8_OES, 0x8B95)
-GLENUM(GL_PALETTE8_RGBA8_OES, 0x8B96)
-GLENUM(GL_PALETTE8_R5_G6_B5_OES, 0x8B97)
-GLENUM(GL_PALETTE8_RGBA4_OES, 0x8B98)
-GLENUM(GL_PALETTE8_RGB5_A1_OES, 0x8B99)
-GLENUM(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, 0x8B9A)
-GLENUM(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, 0x8B9B)
-GLENUM(GL_POINT_SIZE_ARRAY_OES, 0x8B9C)
-GLENUM(GL_TEXTURE_CROP_RECT_OES, 0x8B9D)
-GLENUM(GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES, 0x8B9F)
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index fd97254..37292ee 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -21,10 +21,14 @@
 #include <string.h>
 #include <errno.h>
 
+#include <pthread.h>
+
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES/gl.h>
 #include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 #if !defined(__arm__)
 #define USE_SLOW_BINDING            1
@@ -76,11 +80,15 @@
 
 struct gl_hooks_t {
     struct gl_t {
-        #include "gl_entries.in"
-        #include "glext_entries.in"
+        #include "GLES_CM/gl_entries.in"
+        #include "GLES_CM/glext_entries.in"
     } gl;
+    struct gl2_t {
+        #include "GLES2/gl2_entries.in"
+        #include "GLES2/gl2ext_entries.in"
+    } gl2;
     struct egl_t {
-        #include "egl_entries.in"
+        #include "EGL/egl_entries.in"
     } egl;
     struct gl_ext_t {
         void (*extensions[MAX_NUMBER_OF_GL_EXTENSIONS])(void);
@@ -94,6 +102,13 @@
 
 extern gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
 extern pthread_key_t gGLWrapperKey;
+extern "C" void gl_unimplemented();
+
+extern char const * const gl_names[];
+extern char const * const gl2_names[];
+extern char const * const egl_names[];
+
+// ----------------------------------------------------------------------------
 
 #if USE_FAST_TLS_KEY
 
diff --git a/opengl/libs/tools/enumextract.sh b/opengl/libs/tools/enumextract.sh
deleted file mode 100644
index 5707302..0000000
--- a/opengl/libs/tools/enumextract.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-
-awk '
-/^#define GL_/ {
-    names[count] = $2;
-    values[count] = $3;
-    sort[count] = $3 + 0;
-    count++;
-}
-END {
-    for (i = 1; i < count; i++) {
-        for (j = 0; j < i; j++) {
-            if (sort[i] < sort[j]) {
-                tn = names[i];
-                tv = values[i];
-                ts = sort[i];
-                names[i] = names[j];
-                values[i] = values[j];
-                sort[i] = sort[j];
-                names[j] = tn;
-                values[j] = tv;
-                sort[j] = ts;
-            }
-        }
-    }
- 
-    for (i = 0; i < count; i++) {
-        printf("GLENUM(%s, %s)\n", names[i], values[i]);
-    }
-}
-' < $1
-
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
index 107768b..4f8eda4 100755
--- a/opengl/libs/tools/genfiles
+++ b/opengl/libs/tools/genfiles
@@ -15,6 +15,13 @@
 # limitations under the License.
 
 ./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in 
-./glentrygen ../../include/GLES/gl.h > ../gl_entries.in 
+./glentrygen ../../include/GLES/gl.h > ../GLES_CM/gl_entries.in 
+
 ./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in 
-./glentrygen ../../include/GLES/glext.h > ../glext_entries.in 
+./glentrygen ../../include/GLES/glext.h > ../GLES_CM/glext_entries.in 
+
+./glapigen ../../include/GLES2/gl2.h > ../GLES2/gl2_api.in 
+./glentrygen ../../include/GLES2/gl2.h > ../GLES2/gl2_entries.in 
+
+./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in 
+./glentrygen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_entries.in 
diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen
index a2c3a7b..bd8dda3 100755
--- a/opengl/libs/tools/glapigen
+++ b/opengl/libs/tools/glapigen
@@ -16,16 +16,23 @@
 
 use strict;
 
+sub rtrim($)
+{
+    my $string = shift;
+    $string =~ s/\s+$//;
+    return $string;
+}
+
 while (my $line = <>) {
   next if $line =~ /^\//;
   next if $line =~ /^#/;
   next if $line =~ /^\s*$/;
-  if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
+  if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
     next;
   }
-  my $type = $1;
-  my $name = $2;
-  my $args = $3;
+  my $type = rtrim($2);
+  my $name = $3;
+  my $args = $4;
 
   #printf("%s", $line);
   
diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen
index 5e0f7b6..170f041 100755
--- a/opengl/libs/tools/glentrygen
+++ b/opengl/libs/tools/glentrygen
@@ -16,16 +16,23 @@
 
 use strict;
 
+sub rtrim($)
+{
+    my $string = shift;
+    $string =~ s/\s+$//;
+    return $string;
+}
+
 while (my $line = <>) {
   next if $line =~ /^\//;
   next if $line =~ /^#/;
   next if $line =~ /^\s*$/;
-  if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
+  if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
     next;
   }
-  my $type = $1;
-  my $name = $2;
-  my $args = $3;
+  my $type = rtrim($2);
+  my $name = $3;
+  my $args = $4;
 
   printf("GL_ENTRY(%s, %s, %s)\n", $type, $name, $args);
 }
diff --git a/opengl/tests/copybits/Android.mk b/opengl/tests/copybits/Android.mk
new file mode 100644
index 0000000..2876a1e
--- /dev/null
+++ b/opengl/tests/copybits/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	copybits.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv1_CM \
+    libui
+
+LOCAL_MODULE:= test-opengl-copybits
+
+LOCAL_MODULE_TAGS := tests
+
+##include $(BUILD_EXECUTABLE)
+
diff --git a/opengl/tests/copybits/copybits.cpp b/opengl/tests/copybits/copybits.cpp
new file mode 100644
index 0000000..404932a
--- /dev/null
+++ b/opengl/tests/copybits/copybits.cpp
@@ -0,0 +1,752 @@
+// Test software OpenGL hardware accelleration using copybits.
+
+#define LOG_TAG "copybits_test"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <ui/PixelFormat.h>
+
+#include <cutils/log.h>
+#include <cutils/native_handle.h>
+
+#include <utils/Atomic.h>
+
+#include <private/ui/SharedState.h>
+
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+
+#define EGL_EGLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+extern "C" EGLNativeWindowType android_createDisplaySurface(void);
+
+using namespace android;
+
+EGLDisplay eglDisplay;
+EGLSurface eglSurface;
+EGLContext eglContext;
+GLuint texture;
+
+hw_module_t const* gralloc_module;
+alloc_device_t  *sAllocDev;
+
+#define FIXED_ONE 0x10000 /* 1.0 in 16.16 fixed point. */
+
+int init_gl_surface();
+void free_gl_surface();
+void init_scene();
+
+int create_physical_texture();
+int readTimer();
+
+// ===========================================================================
+// Buffer and implementation of android_native_buffer_t
+// ===========================================================================
+
+class NativeBuffer;
+
+class Buffer :  public android_native_buffer_t,
+                public LightRefBase<Buffer>
+{
+public:
+
+    // creates w * h buffer
+    Buffer(uint32_t w, uint32_t h, PixelFormat format, int usage);
+
+    // return status
+    status_t initCheck() const;
+
+
+    uint32_t getWidth() const           { return mWidth; }
+    uint32_t getHeight() const          { return mHeight; }
+    uint32_t getStride() const          { return mStride; }
+    uint32_t getUsage() const           { return mUsage; }
+    PixelFormat getPixelFormat() const  { return mFormat; }
+    buffer_handle_t getHandle() const   { return mBufferHandle; }
+
+    android_native_buffer_t* getNativeBuffer() const;
+
+    void setPixel(int x, int y, int r, int g, int b, int a);
+
+private:
+    friend class LightRefBase<Buffer>;
+    Buffer(const Buffer& rhs);
+    ~Buffer();
+    Buffer& operator = (const Buffer& rhs);
+    const Buffer& operator = (const Buffer& rhs) const;
+
+    status_t initSize(uint32_t w, uint32_t h);
+
+    static void incRef(android_native_base_t* buffer);
+    static void decRef(android_native_base_t* buffer);
+    static int getHandlePriv(android_native_buffer_t const * buffer,
+            buffer_handle_t* handle);
+
+    buffer_handle_t         mBufferHandle;
+    ssize_t                 mInitCheck;
+
+    uint32_t                mWidth;
+    uint32_t                mHeight;
+    uint32_t                mStride;
+    uint32_t                mVStride;
+    PixelFormat             mFormat;
+    void*                   mData;
+    uint32_t                mUsage;
+};
+
+Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, int usage)
+    : mBufferHandle(0), mInitCheck(NO_INIT),
+    mWidth(0), mHeight(0), mStride(0), mVStride(0), mFormat(format), mData(0),
+    mUsage(usage)
+{
+    common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+    common.version = sizeof(android_native_buffer_t);
+    common.incRef = incRef;
+    common.decRef = decRef;
+    android_native_buffer_t::getHandle = getHandlePriv;
+    if (w>0 && h>0) {
+        mInitCheck = initSize(w, h);
+    }
+}
+
+Buffer::~Buffer()
+{
+    if (mBufferHandle) {
+
+        gralloc_module_t* mod = (gralloc_module_t*)sAllocDev->common.module;
+        mod->unmap(mod, mBufferHandle);
+
+        sAllocDev->free(sAllocDev, mBufferHandle);
+    }
+}
+
+void Buffer::incRef(android_native_base_t* buffer) {
+    Buffer* self = static_cast<Buffer*>(
+            reinterpret_cast<android_native_buffer_t *>(buffer));
+    self->incStrong(self);
+}
+
+void Buffer::decRef(android_native_base_t* buffer) {
+    Buffer* self = static_cast<Buffer*>(
+            reinterpret_cast<android_native_buffer_t *>(buffer));
+    self->decStrong(self);
+}
+
+int Buffer::getHandlePriv(android_native_buffer_t const * buffer,
+        buffer_handle_t* handle) {
+    Buffer const * self = static_cast<Buffer const *>(buffer);
+    *handle = self->getHandle();
+    return 0;
+}
+
+status_t Buffer::initCheck() const {
+    return mInitCheck;
+}
+
+android_native_buffer_t* Buffer::getNativeBuffer() const
+{
+    Buffer* that = const_cast<Buffer*>(this);
+    that->android_native_buffer_t::width = mWidth;
+    that->android_native_buffer_t::height = mHeight;
+    that->android_native_buffer_t::stride = mStride;
+    that->android_native_buffer_t::format = mFormat;
+    that->android_native_buffer_t::usage = mUsage;
+    that->android_native_buffer_t::bits = mData;
+    return static_cast<android_native_buffer_t*>(that);
+}
+
+status_t Buffer::initSize(uint32_t w, uint32_t h)
+{
+    status_t err = NO_ERROR;
+
+    int32_t stride;
+    err = sAllocDev->alloc(sAllocDev, w, h, mFormat, mUsage, &mBufferHandle, &stride);
+
+    if (err == NO_ERROR) {
+        void* addr = 0;
+        gralloc_module_t* mod = (gralloc_module_t*)sAllocDev->common.module;
+        err = mod->map(mod, mBufferHandle, &addr);
+        if (err == NO_ERROR) {
+            mData = addr;
+            mWidth  = w;
+            mHeight = h;
+            mStride = stride;
+            mVStride = 0;
+        }
+    }
+
+    return err;
+}
+
+void Buffer::setPixel(int x, int y, int r, int g, int b, int a) {
+    if (x < 0 || (unsigned int) x >= mWidth
+            || y < 0 || (unsigned int) y >= mHeight) {
+        // clipped
+        return;
+    }
+    int index = mStride * y + x;
+    switch (mFormat) {
+    case HAL_PIXEL_FORMAT_RGB_565: {
+            unsigned short val = (unsigned short) (
+                    ((0x1f & (r >> 3)) << 11)
+                    | ((0x3f & (g >> 2)) << 5)
+                    | (0x1f & (b >> 3)));
+            ((unsigned short*) mData)[index]= val;
+        }
+        break;
+    case HAL_PIXEL_FORMAT_RGBA_8888: { // ABGR
+        unsigned int val = (unsigned int)
+            (((a & 0xff) << 24)
+                    | ((b & 0xff) << 16)
+                    | ((g & 0xff) << 8)
+                    | (r & 0xff));
+            ((unsigned int*) mData)[index] = val;
+        }
+        break;
+    default:
+        // Unsupported pixel format
+        break;
+    }
+}
+
+
+static void gluLookAt(float eyeX, float eyeY, float eyeZ,
+        float centerX, float centerY, float centerZ, float upX, float upY,
+        float upZ)
+{
+    // See the OpenGL GLUT documentation for gluLookAt for a description
+    // of the algorithm. We implement it in a straightforward way:
+
+    float fx = centerX - eyeX;
+    float fy = centerY - eyeY;
+    float fz = centerZ - eyeZ;
+
+    // Normalize f
+    float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz);
+    fx *= rlf;
+    fy *= rlf;
+    fz *= rlf;
+
+    // Normalize up
+    float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ);
+    upX *= rlup;
+    upY *= rlup;
+    upZ *= rlup;
+
+    // compute s = f x up (x means "cross product")
+
+    float sx = fy * upZ - fz * upY;
+    float sy = fz * upX - fx * upZ;
+    float sz = fx * upY - fy * upX;
+
+    // compute u = s x f
+    float ux = sy * fz - sz * fy;
+    float uy = sz * fx - sx * fz;
+    float uz = sx * fy - sy * fx;
+
+    float m[16] ;
+    m[0] = sx;
+    m[1] = ux;
+    m[2] = -fx;
+    m[3] = 0.0f;
+
+    m[4] = sy;
+    m[5] = uy;
+    m[6] = -fy;
+    m[7] = 0.0f;
+
+    m[8] = sz;
+    m[9] = uz;
+    m[10] = -fz;
+    m[11] = 0.0f;
+
+    m[12] = 0.0f;
+    m[13] = 0.0f;
+    m[14] = 0.0f;
+    m[15] = 1.0f;
+
+    glMultMatrixf(m);
+    glTranslatef(-eyeX, -eyeY, -eyeZ);
+}
+
+int init_gralloc() {
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gralloc_module);
+    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+
+    if (err == 0) {
+        gralloc_open(gralloc_module, &sAllocDev);
+    }
+    return err;
+}
+
+int init_gl_surface(void)
+{
+    EGLint numConfigs = 1;
+    EGLConfig myConfig = {0};
+    EGLint attrib[] =
+    {
+            EGL_DEPTH_SIZE,     16,
+            EGL_NONE
+    };
+
+    printf("init_gl_surface\n");
+    if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY )
+    {
+        printf("eglGetDisplay failed\n");
+        return 0;
+    }
+
+    if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE )
+    {
+        printf("eglInitialize failed\n");
+        return 0;
+    }
+
+    if ( eglChooseConfig(eglDisplay, attrib, &myConfig, 1, &numConfigs) != EGL_TRUE )
+    {
+        printf("eglChooseConfig failed\n");
+        return 0;
+    }
+
+    if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig,
+            android_createDisplaySurface(), 0)) == EGL_NO_SURFACE )
+    {
+        printf("eglCreateWindowSurface failed\n");
+        return 0;
+    }
+
+    if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT )
+    {
+        printf("eglCreateContext failed\n");
+        return 0;
+    }
+
+    if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE )
+    {
+        printf("eglMakeCurrent failed\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+void free_gl_surface(void)
+{
+    if (eglDisplay != EGL_NO_DISPLAY)
+    {
+        eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE,
+                EGL_NO_SURFACE, EGL_NO_CONTEXT );
+        eglDestroyContext( eglDisplay, eglContext );
+        eglDestroySurface( eglDisplay, eglSurface );
+        eglTerminate( eglDisplay );
+        eglDisplay = EGL_NO_DISPLAY;
+    }
+}
+
+void init_scene(void)
+{
+    glDisable(GL_DITHER);
+    glEnable(GL_CULL_FACE);
+    float ratio = 320.0f /  480.0f;
+    glViewport(0, 0, 320, 480);
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+
+    glMatrixMode(GL_MODELVIEW);
+
+    glLoadIdentity();
+    gluLookAt(
+            0, 0, 3,  // eye
+            0, 0, 0,  // center
+            0, 1, 0); // up
+
+    glEnable(GL_TEXTURE_2D);
+}
+
+// #define USE_ALPHA_COLOR
+
+#define USE_GL_REPLACE
+// #define USE_GL_MODULATE
+
+// #define USE_BLEND
+
+#define USE_565
+// #define USE_8888
+
+// #define USE_NEAREST
+#define USE_LINEAR
+
+#define USE_SCALE
+
+void setSmoothGradient(Buffer* bufferObject) {
+    int pixels = bufferObject->getHeight() * bufferObject->getWidth();
+    int step = 0;
+    for (unsigned int y = 0; y < bufferObject->getHeight(); y++) {
+        for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) {
+            int grey = step * 255 / pixels;
+            bufferObject->setPixel(x, y, grey, grey, grey, 255);
+            ++step;
+        }
+    }
+}
+
+void setSmoothAlphaGradient(Buffer* bufferObject) {
+    int pixels = bufferObject->getHeight() * bufferObject->getWidth();
+    int step = 0;
+    for (unsigned int y = 0; y < bufferObject->getHeight(); y++) {
+        for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) {
+            int grey = step * 255 / pixels;
+            bufferObject->setPixel(x, y, 255, 255, 255, grey);
+            ++step;
+        }
+    }
+}
+
+void setOrientedCheckerboard(Buffer* bufferObject) {
+    bufferObject->setPixel(0, 0, 0, 0, 0, 255);
+    for(unsigned int x = 1; x < bufferObject->getWidth() ; x++) {
+        bufferObject->setPixel(x, 0, 0, 255, 0, 255);
+    }
+    for (unsigned int y = 1; y < bufferObject->getHeight(); y++) {
+        for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) {
+            if ((x ^ y ) & 1) {
+                bufferObject->setPixel(x, y, 255, 255, 255, 255);
+            } else {
+                bufferObject->setPixel(x, y, 255, 0, 0, 255);
+            }
+        }
+    }
+}
+
+int create_physical_texture(unsigned int w, unsigned int h)
+{
+
+#ifdef USE_565
+    PixelFormat format = HAL_PIXEL_FORMAT_RGB_565;
+#else
+    PixelFormat format = HAL_PIXEL_FORMAT_RGBA_8888;
+#endif
+    int usage = GRALLOC_USAGE_SW_READ_OFTEN |
+        GRALLOC_USAGE_SW_WRITE_OFTEN |
+        GRALLOC_USAGE_HW_TEXTURE |
+        GRALLOC_USAGE_HW_2D; /* This is the key to allocating the texture in pmem. */
+    int32_t stride;
+    buffer_handle_t handle;
+
+    // Allocate the hardware buffer
+    Buffer* bufferObject = new Buffer(w, h, format, usage);
+
+    android_native_buffer_t* buffer = bufferObject->getNativeBuffer();
+
+    buffer->common.incRef(&buffer->common);
+
+    // create the new EGLImageKHR
+    EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_NONE };
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+            (EGLClientBuffer)buffer, attrs);
+    if (image == EGL_NO_IMAGE_KHR) {
+        printf("Could not create an image %d\n", eglGetError());
+        return -1;
+    }
+
+    if (buffer->bits == NULL) {
+        printf("No bits allocated for image.\n");
+        return -2;
+    }
+
+    setOrientedCheckerboard(bufferObject);
+    // setSmoothGradient(bufferObject);
+    // setSmoothAlphaGradient(bufferObject);
+
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+#ifdef USE_LINEAR
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#elif defined(USE_NEAREST)
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+#endif
+
+#ifdef USE_GL_REPLACE
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+#elif defined(USE_GL_MODULATE)
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+#endif
+
+#ifdef USE_ALPHA_COLOR
+    glColor4f(1.0f, 1.0f, 1.0f, 0.4f);
+#else
+    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+#endif
+
+#ifdef USE_BLEND
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+#endif
+    return 0;
+}
+
+static const int SCALE_COUNT = 12;
+
+int scale(int base, int factor) {
+    static const float kTable[SCALE_COUNT] = {
+            0.1f, 0.25f, 0.5f, 0.75f, 1.0f,
+            1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 5.0f
+    };
+    return base * kTable[factor];
+}
+
+class Timer {
+    struct timeval  first;
+    double elapsedSeconds;
+
+public:
+    Timer() {}
+    void start() {
+        gettimeofday(&first, NULL);
+    }
+
+    void stop() {
+        struct timeval  second,
+                        elapsed;
+        gettimeofday(&second, NULL);
+
+        if (first.tv_usec > second.tv_usec) {
+           second.tv_usec += 1000000;
+           second.tv_sec--;
+        }
+
+        elapsedSeconds = (second.tv_sec  - first.tv_sec) +
+            (second.tv_usec - first.tv_usec) / 1000000.0;
+    }
+
+    double getElapsedSeconds() {
+        return elapsedSeconds;
+    }
+
+    double getElapsedMs() {
+        return elapsedSeconds* 1000.0f;
+    }
+};
+
+int testTime()
+{
+    static const int WIDTH = 320;
+    static const int HEIGHT = 480;
+    static const int SCALE = 8;
+
+    if (create_physical_texture(WIDTH, HEIGHT) != 0) {
+        return -1;
+    }
+    // Need to do a dummy eglSwapBuffers first. Don't know why.
+    glClearColor(0.4, 1.0, 0.4, 0.4);
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    eglSwapBuffers(eglDisplay, eglSurface);
+
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+#if defined(USE_SCALE)
+    static const int scaleOffset = 0;
+#else
+    static const int scaleOffset = 1;
+#endif
+    printf("ms\n");
+    for(int j = 0; j < SCALE; j++) {
+        int w = WIDTH >> (j + scaleOffset);
+        int h = HEIGHT >> j;
+        int cropRect[4] = {0,h,w,-h}; // Left bottom width height. Width and Height can be neg to flip.
+        glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
+        Timer timer;
+        timer.start();
+
+        int copyCount = 1000;
+        for (int i = 0; i < copyCount; i++) {
+            glDrawTexiOES(0, 0, 0, w, h);
+        }
+
+        timer.stop();
+        printf("%g\n", timer.getElapsedMs() / copyCount);
+    }
+
+    eglSwapBuffers(eglDisplay, eglSurface);
+    return 0;
+}
+
+int testStretch()
+{
+    static const int WIDTH = 8;
+    static const int HEIGHT = 8;
+
+    if (create_physical_texture(WIDTH, HEIGHT) != 0) {
+        return -1;
+    }
+    // Need to do a dummy eglSwapBuffers first. Don't know why.
+    glClearColor(0.4, 1.0, 0.4, 0.4);
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    eglSwapBuffers(eglDisplay, eglSurface);
+
+    int cropRect[4] = {0,HEIGHT,WIDTH,-HEIGHT}; // Left bottom width height. Width and Height can be neg to flip.
+    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
+
+    for(int frame = 0; frame < 2; frame++) {
+        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+        int baseX = 10;
+        for (int x = 0; x < SCALE_COUNT; x++) {
+            int baseY = 10;
+            int width = scale(WIDTH, x);
+            for (int y = 0; y < SCALE_COUNT; y++) {
+                int height = scale(HEIGHT, y);
+                glDrawTexxOES(baseX << 16, baseY << 16, 0, width << 16, height << 16);
+                baseY += height + 10;
+            }
+            baseX += width + 10;
+        }
+
+        eglSwapBuffers(eglDisplay, eglSurface);
+    }
+    return 0;
+}
+
+int testRot90()
+{
+    static const int WIDTH = 8;
+    static const int HEIGHT = 8;
+
+    if (create_physical_texture(WIDTH, HEIGHT) != 0) {
+        return -1;
+    }
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrthof(0, 320, 480, 0, 0, 1);
+
+    glMatrixMode(GL_MODELVIEW);
+
+    glLoadIdentity();
+
+    // Need to do a dummy eglSwapBuffers first. Don't know why.
+    glClearColor(0.4, 0.4, 0.4, 0.4);
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    eglSwapBuffers(eglDisplay, eglSurface);
+
+    glEnable(GL_TEXTURE_2D);
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
+    glDisable(GL_BLEND);
+    glShadeModel(GL_FLAT);
+    glDisable(GL_DITHER);
+    glDisable(GL_CULL_FACE);
+
+    for(int frame = 0; frame < 2; frame++) {
+        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+        int baseX = 10;
+        for (int x = 0; x < SCALE_COUNT; x++) {
+            int baseY = 10;
+            int width = scale(WIDTH, x);
+            for (int y = 0; y < SCALE_COUNT; y++) {
+                int height = scale(HEIGHT, y);
+
+                // Code copied from SurfaceFlinger LayerBase.cpp
+
+                const GLfixed texCoords[4][2] = {
+                        { 0,        0 },
+                        { 0,        0x10000 },
+                        { 0x10000,  0x10000 },
+                        { 0x10000,  0 }
+                };
+
+                GLfixed fx = baseX << 16;
+                GLfixed fy = baseY << 16;
+                GLfixed fw = width << 16;
+                GLfixed fh = height << 16;
+
+                /*
+                 * Vertex pattern:
+                 *    (2)--(3)
+                 *     |\   |
+                 *     | \  |
+                 *     |  \ |
+                 *     |   \|
+                 *    (1)--(0)
+                 *
+                 */
+
+                const GLfixed vertices[4][2] = {
+                        {fx + fw, fy},
+                        {fx,      fy},
+                        {fx,      fy + fh},
+                        {fx + fw, fy + fh}
+                };
+
+                static const bool rotate90 = true;
+
+                glMatrixMode(GL_TEXTURE);
+                glLoadIdentity();
+
+                glEnableClientState(GL_VERTEX_ARRAY);
+                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+                glVertexPointer(2, GL_FIXED, 0, vertices);
+                glTexCoordPointer(2, GL_FIXED, 0, texCoords);
+
+                LOGW("testRot90 %d, %d %d, %d", baseX, baseY, width, height);
+                glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+                baseY += height + 10;
+            }
+            baseX += width + 10;
+        }
+
+        eglSwapBuffers(eglDisplay, eglSurface);
+    }
+    return 0;
+}
+
+int main(int argc, char **argv)
+{
+
+    int q;
+    int start, end;
+
+    if (init_gralloc()) {
+        printf("gralloc initialization failed - exiting\n");
+        return 0;
+    }
+
+    printf("Initializing EGL...\n");
+
+    if(!init_gl_surface())
+    {
+        printf("GL initialisation failed - exiting\n");
+        return 0;
+    }
+
+    init_scene();
+
+    printf("Start test...\n");
+    // testTime();
+    // testStretch();
+    testRot90();
+    free_gl_surface();
+
+    return 0;
+}