auto import from //depot/cupcake/@135843
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
new file mode 100644
index 0000000..496e271
--- /dev/null
+++ b/libs/surfaceflinger/Android.mk
@@ -0,0 +1,49 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    clz.cpp.arm \
+    DisplayHardware/DisplayHardware.cpp \
+    DisplayHardware/DisplayHardwareBase.cpp \
+    GPUHardware/GPUHardware.cpp \
+    BootAnimation.cpp \
+    BlurFilter.cpp.arm \
+    CPUGauge.cpp \
+    Layer.cpp \
+    LayerBase.cpp \
+    LayerBuffer.cpp \
+    LayerBlur.cpp \
+    LayerBitmap.cpp \
+    LayerDim.cpp \
+    LayerOrientationAnim.cpp \
+    OrientationAnimation.cpp \
+    SurfaceFlinger.cpp \
+    Tokenizer.cpp \
+    Transform.cpp \
+    VRamHeap.cpp
+
+
+# need "-lrt" on Linux simulator to pick up clock_gettime
+ifeq ($(TARGET_SIMULATOR),true)
+	ifeq ($(HOST_OS),linux)
+		LOCAL_LDLIBS += -lrt
+	endif
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+	libhardware \
+	libutils \
+	libcutils \
+	libui \
+	libcorecg \
+	libsgl \
+	libpixelflinger \
+	libEGL \
+	libGLESv1_CM
+
+LOCAL_C_INCLUDES := \
+	$(call include-path-for, corecg graphics)
+
+LOCAL_MODULE:= libsurfaceflinger
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/surfaceflinger/Barrier.h b/libs/surfaceflinger/Barrier.h
new file mode 100644
index 0000000..e2bcf6a
--- /dev/null
+++ b/libs/surfaceflinger/Barrier.h
@@ -0,0 +1,59 @@
+/*
+ * 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_BARRIER_H
+#define ANDROID_BARRIER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class Barrier
+{
+public:
+    inline Barrier() : state(CLOSED) { }
+    inline ~Barrier() { }
+    void open() {
+        // gcc memory barrier, this makes sure all memory writes
+        // have been issued by gcc. On an SMP system we'd need a real
+        // h/w barrier.
+        asm volatile ("":::"memory");
+        Mutex::Autolock _l(lock);
+        state = OPENED;
+        cv.broadcast();
+    }
+    void close() {
+        Mutex::Autolock _l(lock);
+        state = CLOSED;
+    }
+    void wait() const {
+        Mutex::Autolock _l(lock);
+        while (state == CLOSED) {
+            cv.wait(lock);
+        }
+    }
+private:
+    enum { OPENED, CLOSED };
+    mutable     Mutex       lock;
+    mutable     Condition   cv;
+    volatile    int         state;
+};
+
+}; // namespace android
+
+#endif // ANDROID_BARRIER_H
diff --git a/libs/surfaceflinger/BlurFilter.cpp b/libs/surfaceflinger/BlurFilter.cpp
new file mode 100644
index 0000000..5dc0ba0
--- /dev/null
+++ b/libs/surfaceflinger/BlurFilter.cpp
@@ -0,0 +1,326 @@
+/* 
+**
+** 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 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT 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 <string.h>
+#include <stdint.h>
+#include <utils/Errors.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+#include "clz.h"
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+inline uint32_t BLUR_RGBA_TO_HOST(uint32_t v) {
+    return v;
+}
+inline uint32_t BLUR_HOST_TO_RGBA(uint32_t v) {
+    return v;
+}
+#else
+inline uint32_t BLUR_RGBA_TO_HOST(uint32_t v) {
+    return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
+}
+inline uint32_t BLUR_HOST_TO_RGBA(uint32_t v) {
+    return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
+}
+#endif
+
+const int BLUR_DITHER_BITS = 6;  // dither weights stored on 6 bits
+const int BLUR_DITHER_ORDER_SHIFT= 3;
+const int BLUR_DITHER_ORDER      = (1<<BLUR_DITHER_ORDER_SHIFT);
+const int BLUR_DITHER_SIZE       = BLUR_DITHER_ORDER * BLUR_DITHER_ORDER;
+const int BLUR_DITHER_MASK       = BLUR_DITHER_ORDER-1;
+
+static const uint8_t gDitherMatrix[BLUR_DITHER_SIZE] = {
+     0, 32,  8, 40,  2, 34, 10, 42,
+    48, 16, 56, 24, 50, 18, 58, 26,
+    12, 44,  4, 36, 14, 46,  6, 38,
+    60, 28, 52, 20, 62, 30, 54, 22,
+     3, 35, 11, 43,  1, 33,  9, 41,
+    51, 19, 59, 27, 49, 17, 57, 25,
+    15, 47,  7, 39, 13, 45,  5, 37,
+    63, 31, 55, 23, 61, 29, 53, 21
+};
+
+
+template <int FACTOR = 0>
+struct BlurColor565
+{
+    typedef uint16_t type;
+    int r, g, b;    
+    inline BlurColor565() { }
+    inline BlurColor565(uint16_t v) {
+        r = v >> 11;
+        g = (v >> 5) & 0x3E;
+        b = v & 0x1F;
+    }
+    inline void clear() { r=g=b=0; }
+    inline uint16_t to(int shift, int last, int dither) const {
+        int R = r;
+        int G = g;
+        int B = b;
+        if  (UNLIKELY(last)) {
+            if (FACTOR>0) {
+                int L = (R+G+B)>>1;
+                R += (((L>>1) - R) * FACTOR) >> 8;
+                G += (((L   ) - G) * FACTOR) >> 8;
+                B += (((L>>1) - B) * FACTOR) >> 8;
+            }
+            R += (dither << shift) >> BLUR_DITHER_BITS;
+            G += (dither << shift) >> BLUR_DITHER_BITS;
+            B += (dither << shift) >> BLUR_DITHER_BITS;
+        }
+        R >>= shift;
+        G >>= shift;
+        B >>= shift;
+        return (R<<11) | (G<<5) | B;
+    }    
+    inline BlurColor565& operator += (const BlurColor565& rhs) {
+        r += rhs.r;
+        g += rhs.g;
+        b += rhs.b;
+        return *this;
+    }
+    inline BlurColor565& operator -= (const BlurColor565& rhs) {
+        r -= rhs.r;
+        g -= rhs.g;
+        b -= rhs.b;
+        return *this;
+    }
+};
+
+struct BlurGray565
+{
+    typedef uint16_t type;
+    int l;    
+    inline BlurGray565() { }
+    inline BlurGray565(uint16_t v) {
+        int r = v >> 11;
+        int g = (v >> 5) & 0x3F;
+        int b = v & 0x1F;
+        l = (r + g + b + 1)>>1;
+    }
+    inline void clear() { l=0; }
+    inline uint16_t to(int shift, int last, int dither) const {
+        int L = l;
+        if  (UNLIKELY(last)) {
+            L += (dither << shift) >> BLUR_DITHER_BITS;
+        }
+        L >>= shift;
+        return ((L>>1)<<11) | (L<<5) | (L>>1);
+    }
+    inline BlurGray565& operator += (const BlurGray565& rhs) {
+        l += rhs.l;
+        return *this;
+    }
+    inline BlurGray565& operator -= (const BlurGray565& rhs) {
+        l -= rhs.l;
+        return *this;
+    }
+};
+
+struct BlurGray8888
+{
+    typedef uint32_t type;
+    int l, a;    
+    inline BlurGray8888() { }
+    inline BlurGray8888(uint32_t v) {
+        v = BLUR_RGBA_TO_HOST(v);
+        int r = v & 0xFF;
+        int g = (v >>  8) & 0xFF;
+        int b = (v >> 16) & 0xFF;
+        a = v >> 24;
+        l = r + g + g + b;
+    }    
+    inline void clear() { l=a=0; }
+    inline uint32_t to(int shift, int last, int dither) const {
+        int L = l;
+        int A = a;
+        if  (UNLIKELY(last)) {
+            L += (dither << (shift+2)) >> BLUR_DITHER_BITS;
+            A += (dither << shift) >> BLUR_DITHER_BITS;
+        }
+        L >>= (shift+2);
+        A >>= shift;
+        return BLUR_HOST_TO_RGBA((A<<24) | (L<<16) | (L<<8) | L);
+    }
+    inline BlurGray8888& operator += (const BlurGray8888& rhs) {
+        l += rhs.l;
+        a += rhs.a;
+        return *this;
+    }
+    inline BlurGray8888& operator -= (const BlurGray8888& rhs) {
+        l -= rhs.l;
+        a -= rhs.a;
+        return *this;
+    }
+};
+
+
+template<typename PIXEL>
+static status_t blurFilter(
+        GGLSurface const* dst,
+        GGLSurface const* src,
+        int kernelSizeUser,
+        int repeat)
+{
+    typedef typename PIXEL::type TYPE;
+
+    const int shift             = 31 - clz(kernelSizeUser);
+    const int areaShift         = shift*2;
+    const int kernelSize        = 1<<shift;
+    const int kernelHalfSize    = kernelSize/2;
+    const int mask              = kernelSize-1;
+    const int w                 = src->width;
+    const int h                 = src->height;
+    const uint8_t* ditherMatrix = gDitherMatrix;
+
+    // we need a temporary buffer to store one line of blurred columns
+    // as well as kernelSize lines of source pixels organized as a ring buffer.
+    void* const temporary_buffer = malloc(
+            (w + kernelSize) * sizeof(PIXEL) +
+            (src->stride * kernelSize) * sizeof(TYPE));
+    if (!temporary_buffer)
+        return NO_MEMORY;
+
+    PIXEL* const sums = (PIXEL*)temporary_buffer;
+    TYPE* const scratch = (TYPE*)(sums + w + kernelSize);
+
+    // Apply the blur 'repeat' times, this is used to approximate
+    // gaussian blurs. 3 times gives good results.
+    for (int k=0 ; k<repeat ; k++) {
+
+        // Clear the columns sums for this round
+        memset(sums, 0, (w + kernelSize) * sizeof(PIXEL));
+        TYPE* head;
+        TYPE pixel;
+        PIXEL current;
+
+        // Since we're going to override the source data we need
+        // to copy it in a temporary buffer. Only kernelSize lines are
+        // required. But since we start in the center of the kernel,
+        // we only copy half of the data, and fill the rest with zeros
+        // (assuming black/transparent pixels).
+        memcpy( scratch + src->stride*kernelHalfSize,
+                src->data,
+                src->stride*kernelHalfSize*sizeof(TYPE));
+
+        // sum half of each column, because we assume the first half is
+        // zeros (black/transparent).
+        for (int y=0 ; y<kernelHalfSize ; y++) {
+            head = (TYPE*)src->data + y*src->stride;
+            for (int x=0 ; x<w ; x++)
+                sums[x] += PIXEL( *head++ );
+        }
+
+        for (int y=0 ; y<h ; y++) {
+            TYPE* fb = (TYPE*)dst->data + y*dst->stride;
+
+            // compute the dither matrix line
+            uint8_t const * ditherY = ditherMatrix
+                    + (y & BLUR_DITHER_MASK)*BLUR_DITHER_ORDER;
+
+            // Horizontal blur pass on the columns sums
+            int count, dither, x=0;
+            PIXEL const * out= sums;
+            PIXEL const * in = sums;
+            current.clear();
+
+            count = kernelHalfSize;
+            do {
+                current += *in;
+                in++;
+            } while (--count);
+            
+            count = kernelHalfSize;
+            do {
+                current += *in;
+                dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
+                *fb++ = current.to(areaShift, k==repeat-1, dither);
+                in++;
+            } while (--count);
+
+            count = w-kernelSize;
+            do {
+                current += *in;
+                current -= *out;
+                dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
+                *fb++ = current.to(areaShift, k==repeat-1, dither);
+                in++, out++;
+            } while (--count);
+
+            count = kernelHalfSize;
+            do {
+                current -= *out;
+                dither = *(ditherY + ((x++)&BLUR_DITHER_MASK));
+                *fb++ = current.to(areaShift, k==repeat-1, dither);
+                out++;
+            } while (--count);
+
+            // vertical blur pass, subtract the oldest line from each columns
+            // and add a new line. Subtract or add zeros at the top
+            // and bottom edges.
+            TYPE* const tail = scratch + (y & mask) * src->stride;
+            if (y >= kernelHalfSize) {
+                for (int x=0 ; x<w ; x++)
+                    sums[x] -= PIXEL( tail[x] );
+            }
+            if (y < h-kernelSize) {
+                memcpy( tail,
+                        (TYPE*)src->data + (y+kernelHalfSize)*src->stride,
+                        src->stride*sizeof(TYPE));
+                for (int x=0 ; x<w ; x++)
+                    sums[x] += PIXEL( tail[x] );
+            }
+        }
+
+        // The subsequent passes are always done in-place.
+        src = dst;
+    }
+    
+    free(temporary_buffer);
+
+    return NO_ERROR;
+}
+
+template status_t blurFilter< BlurColor565<0x80> >(
+        GGLSurface const* dst,
+        GGLSurface const* src,
+        int kernelSizeUser,
+        int repeat);
+
+status_t blurFilter(
+        GGLSurface const* image,
+        int kernelSizeUser,
+        int repeat)
+{
+    return blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+}
+
+} // namespace android
+
+//err = blur< BlurColor565<0x80> >(dst, src, kernelSizeUser, repeat);
+//err = blur<BlurGray565>(dst, src, kernelSizeUser, repeat);
+//err = blur<BlurGray8888>(dst, src, kernelSizeUser, repeat);
diff --git a/libs/surfaceflinger/BlurFilter.h b/libs/surfaceflinger/BlurFilter.h
new file mode 100644
index 0000000..294db43
--- /dev/null
+++ b/libs/surfaceflinger/BlurFilter.h
@@ -0,0 +1,35 @@
+/* 
+**
+** 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 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT 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_BLUR_FILTER_H
+#define ANDROID_BLUR_FILTER_H
+
+#include <stdint.h>
+#include <utils/Errors.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+namespace android {
+
+status_t blurFilter(
+        GGLSurface const* image,
+        int kernelSizeUser,
+        int repeat);
+
+} // namespace android
+
+#endif // ANDROID_BLUR_FILTER_H
diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp
new file mode 100644
index 0000000..2b30336
--- /dev/null
+++ b/libs/surfaceflinger/BootAnimation.cpp
@@ -0,0 +1,403 @@
+/*
+ * 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 "BootAnimation"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <math.h>
+#include <fcntl.h>
+#include <utils/misc.h>
+
+#include <utils/threads.h>
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/AssetManager.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 <ui/EGLNativeWindowSurface.h>
+
+#include <core/SkBitmap.h>
+#include <images/SkImageDecoder.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <EGL/eglext.h>
+
+#include "BootAnimation.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) :
+    Thread(false) {
+    mSession = SurfaceComposerClient::clientForConnection(
+            composer->createConnection()->asBinder());
+}
+
+BootAnimation::~BootAnimation() {
+}
+
+void BootAnimation::onFirstRef() {
+    run("BootAnimation", PRIORITY_DISPLAY);
+}
+
+const sp<SurfaceComposerClient>& BootAnimation::session() const {
+    return mSession;
+}
+
+status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
+        const char* name) {
+    Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
+    if (!asset)
+        return NO_INIT;
+    SkBitmap bitmap;
+    SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
+            &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
+    asset->close();
+    delete asset;
+
+    // ensure we can call getPixels(). No need to call unlock, since the
+    // bitmap will go out of scope when we return from this method.
+    bitmap.lockPixels();
+
+    const int w = bitmap.width();
+    const int h = bitmap.height();
+    const void* p = bitmap.getPixels();
+
+    GLint crop[4] = { 0, h, w, -h };
+    texture->w = w;
+    texture->h = h;
+
+    glGenTextures(1, &texture->name);
+    glBindTexture(GL_TEXTURE_2D, texture->name);
+
+    switch (bitmap.getConfig()) {
+        case SkBitmap::kA8_Config:
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA,
+                    GL_UNSIGNED_BYTE, p);
+            break;
+        case SkBitmap::kARGB_4444_Config:
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
+                    GL_UNSIGNED_SHORT_4_4_4_4, p);
+            break;
+        case SkBitmap::kARGB_8888_Config:
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
+                    GL_UNSIGNED_BYTE, p);
+            break;
+        case SkBitmap::kRGB_565_Config:
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
+                    GL_UNSIGNED_SHORT_5_6_5, p);
+            break;
+        default:
+            break;
+    }
+
+    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    return NO_ERROR;
+}
+
+status_t BootAnimation::readyToRun() {
+    mAssets.addDefaultAssets();
+
+    DisplayInfo dinfo;
+    status_t status = session()->getDisplayInfo(0, &dinfo);
+    if (status)
+        return -1;
+
+    // create the native surface
+    sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h,
+            PIXEL_FORMAT_RGB_565);
+    session()->openTransaction();
+    s->setLayer(0x40000000);
+    session()->closeTransaction();
+
+    // 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 };
+    EGLint w, h, dummy;
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLSurface surface;
+    EGLContext context;
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
+
+    mNativeWindowSurface = new EGLNativeWindowSurface(s);
+    surface = eglCreateWindowSurface(display, config, 
+            mNativeWindowSurface.get(), NULL);
+
+    context = eglCreateContext(display, config, NULL, NULL);
+    eglQuerySurface(display, surface, EGL_WIDTH, &w);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
+    eglMakeCurrent(display, surface, surface, context);
+    mDisplay = display;
+    mContext = context;
+    mSurface = surface;
+    mWidth = w;
+    mHeight = h;
+    mFlingerSurface = s;
+
+    // initialize GL
+    glShadeModel(GL_FLAT);
+    glEnable(GL_DITHER);
+    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_SCISSOR_TEST);
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+    return NO_ERROR;
+}
+
+void BootAnimation::requestExit() {
+    mBarrier.open();
+    Thread::requestExit();
+}
+
+bool BootAnimation::threadLoop() {
+    bool r = android();
+    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroyContext(mDisplay, mContext);
+    eglDestroySurface(mDisplay, mSurface);
+    mNativeWindowSurface.clear();
+    return r;
+}
+
+bool BootAnimation::android() {
+    initTexture(&mAndroid[0], mAssets, "images/android_320x480.png");
+    initTexture(&mAndroid[1], mAssets, "images/boot_robot.png");
+    initTexture(&mAndroid[2], mAssets, "images/boot_robot_glow.png");
+
+    // erase screen
+    glDisable(GL_SCISSOR_TEST);
+    glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
+
+    // clear screen
+    glClear(GL_COLOR_BUFFER_BIT);
+    eglSwapBuffers(mDisplay, mSurface);
+
+    // wait ~1s
+    usleep(800000);
+
+    // fade in
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    const int steps = 8;
+    for (int i = 1; i < steps; i++) {
+        float fade = i / float(steps);
+        glColor4f(1, 1, 1, fade * fade);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h);
+        eglSwapBuffers(mDisplay, mSurface);
+    }
+
+    // draw last frame
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    glDisable(GL_BLEND);
+    glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h);
+    eglSwapBuffers(mDisplay, mSurface);
+
+    // update rect for the robot
+    const int x = mWidth - mAndroid[1].w - 33;
+    const int y = (mHeight - mAndroid[1].h) / 2 - 1;
+    const Rect updateRect(x, y, x + mAndroid[1].w, y + mAndroid[1].h);
+
+    // draw and update only what we need
+    mNativeWindowSurface->setSwapRectangle(updateRect.left,
+            updateRect.top, updateRect.width(), updateRect.height());
+
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
+            updateRect.height());
+
+    const nsecs_t startTime = systemTime();
+    do {
+        // glow speed and shape
+        nsecs_t time = systemTime() - startTime;
+        float t = ((4.0f / (360.0f * us2ns(16667))) * time);
+        t = t - floorf(t);
+        const float fade = 0.5f + 0.5f * sinf(t * 2 * M_PI);
+
+        // fade the glow in and out
+        glDisable(GL_BLEND);
+        glBindTexture(GL_TEXTURE_2D, mAndroid[2].name);
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+        glColor4f(fade, fade, fade, fade);
+        glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0,
+                updateRect.width(), updateRect.height());
+
+        // draw the robot
+        glEnable(GL_BLEND);
+        glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0,
+                updateRect.width(), updateRect.height());
+
+        // make sure sleep a lot to not take too much CPU away from 
+        // the boot process. With this "glow" animation there is no
+        // visible difference. 
+        usleep(16667 * 4);
+
+        eglSwapBuffers(mDisplay, mSurface);
+    } while (!exitPending());
+
+    glDeleteTextures(1, &mAndroid[0].name);
+    glDeleteTextures(1, &mAndroid[1].name);
+    glDeleteTextures(1, &mAndroid[2].name);
+    return false;
+}
+
+bool BootAnimation::cylon() {
+    // initialize the textures...
+    initTexture(&mLeftTrail, mAssets, "images/cylon_left.png");
+    initTexture(&mRightTrail, mAssets, "images/cylon_right.png");
+    initTexture(&mBrightSpot, mAssets, "images/cylon_dot.png");
+
+    int w = mWidth;
+    int h = mHeight;
+
+    const Point c(w / 2, h / 2);
+    const GLint amplitude = 60;
+    const int scx = c.x - amplitude - mBrightSpot.w / 2;
+    const int scy = c.y - mBrightSpot.h / 2;
+    const int scw = amplitude * 2 + mBrightSpot.w;
+    const int sch = mBrightSpot.h;
+    const Rect updateRect(scx, h - scy - sch, scx + scw, h - scy);
+
+    // erase screen
+    glDisable(GL_SCISSOR_TEST);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    eglSwapBuffers(mDisplay, mSurface);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    mNativeWindowSurface->setSwapRectangle(updateRect.left,
+            updateRect.top, updateRect.width(), updateRect.height());
+
+    glEnable(GL_SCISSOR_TEST);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+    // clear the screen to white
+    Point p;
+    float t = 0;
+    float alpha = 1.0f;
+    const nsecs_t startTime = systemTime();
+    nsecs_t fadeTime = 0;
+
+    do {
+        // Set scissor in interesting area
+        glScissor(scx, scy, scw, sch);
+
+        // erase screen
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        // compute wave
+        const float a = (t * 2 * M_PI) - M_PI / 2;
+        const float sn = sinf(a);
+        const float cs = cosf(a);
+        GLint x = GLint(amplitude * sn);
+        float derivative = cs;
+
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+        if (derivative > 0) {
+            // vanishing trail...
+            p.x = (-amplitude + c.x) - mBrightSpot.w / 2;
+            p.y = c.y - mLeftTrail.h / 2;
+            float fade = 2.0f * (0.5f - t);
+            //fade *= fade;
+            glColor4f(fade, fade, fade, fade);
+            glBindTexture(GL_TEXTURE_2D, mLeftTrail.name);
+            glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h);
+
+            // trail...
+            p.x = (x + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16;
+            p.y = c.y - mRightTrail.h / 2;
+            fade = t < 0.25f ? t * 4.0f : 1.0f;
+            fade *= fade;
+            glColor4f(fade, fade, fade, fade);
+            glBindTexture(GL_TEXTURE_2D, mRightTrail.name);
+            glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h);
+        } else {
+            // vanishing trail..
+            p.x = (amplitude + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16;
+            p.y = c.y - mRightTrail.h / 2;
+            float fade = 2.0f * (0.5f - (t - 0.5f));
+            //fade *= fade;
+            glColor4f(fade, fade, fade, fade);
+            glBindTexture(GL_TEXTURE_2D, mRightTrail.name);
+            glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h);
+
+            // trail...
+            p.x = (x + c.x) - mBrightSpot.w / 2;
+            p.y = c.y - mLeftTrail.h / 2;
+            fade = t < 0.5f + 0.25f ? (t - 0.5f) * 4.0f : 1.0f;
+            fade *= fade;
+            glColor4f(fade, fade, fade, fade);
+            glBindTexture(GL_TEXTURE_2D, mLeftTrail.name);
+            glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h);
+        }
+
+        const Point p(x + c.x - mBrightSpot.w / 2, c.y - mBrightSpot.h / 2);
+        glBindTexture(GL_TEXTURE_2D, mBrightSpot.name);
+        glColor4f(1, 0.5, 0.5, 1);
+        glDrawTexiOES(p.x, p.y, 0, mBrightSpot.w, mBrightSpot.h);
+
+        // update animation
+        nsecs_t time = systemTime() - startTime;
+        t = ((4.0f / (360.0f * us2ns(16667))) * time);
+        t = t - floorf(t);
+
+        eglSwapBuffers(mDisplay, mSurface);
+
+        if (exitPending()) {
+            if (fadeTime == 0) {
+                fadeTime = time;
+            }
+            time -= fadeTime;
+            alpha = 1.0f - ((float(time) * 6.0f) / float(s2ns(1)));
+
+            session()->openTransaction();
+            mFlingerSurface->setAlpha(alpha * alpha);
+            session()->closeTransaction();
+        }
+    } while (alpha > 0);
+
+    // cleanup
+    glFinish();
+    glDeleteTextures(1, &mLeftTrail.name);
+    glDeleteTextures(1, &mRightTrail.name);
+    glDeleteTextures(1, &mBrightSpot.name);
+    return false;
+}
+
+// ---------------------------------------------------------------------------
+
+}
+; // namespace android
diff --git a/libs/surfaceflinger/BootAnimation.h b/libs/surfaceflinger/BootAnimation.h
new file mode 100644
index 0000000..b20cea0
--- /dev/null
+++ b/libs/surfaceflinger/BootAnimation.h
@@ -0,0 +1,87 @@
+/*
+ * 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_BOOTANIMATION_H
+#define ANDROID_BOOTANIMATION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+#include <utils/AssetManager.h>
+
+#include <ui/ISurfaceComposer.h>
+#include <ui/SurfaceComposerClient.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+
+#include "Barrier.h"
+
+class SkBitmap;
+
+namespace android {
+
+class AssetManager;
+class EGLNativeWindowSurface;
+
+// ---------------------------------------------------------------------------
+
+class BootAnimation : public Thread
+{
+public:
+                BootAnimation(const sp<ISurfaceComposer>& composer);
+    virtual     ~BootAnimation();
+
+    const sp<SurfaceComposerClient>& session() const;
+    virtual void        requestExit();
+
+private:
+    virtual bool        threadLoop();
+    virtual status_t    readyToRun();
+    virtual void        onFirstRef();
+
+    struct Texture {
+        GLint   w;
+        GLint   h;
+        GLuint  name;
+    };
+
+    status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
+    bool android();
+    bool cylon();
+
+    sp<SurfaceComposerClient>       mSession;
+    AssetManager mAssets;
+    Texture mLeftTrail;
+    Texture mRightTrail;
+    Texture mBrightSpot;
+    Texture mAndroid[3];
+    int     mWidth;
+    int     mHeight;
+    EGLDisplay  mDisplay;
+    EGLDisplay  mContext;
+    EGLDisplay  mSurface;
+    sp<Surface> mFlingerSurface;
+    sp<EGLNativeWindowSurface> mNativeWindowSurface;
+    Barrier mBarrier;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_BOOTANIMATION_H
diff --git a/libs/surfaceflinger/CPUGauge.cpp b/libs/surfaceflinger/CPUGauge.cpp
new file mode 100644
index 0000000..74a9270
--- /dev/null
+++ b/libs/surfaceflinger/CPUGauge.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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
new file mode 100644
index 0000000..5bb53c0
--- /dev/null
+++ b/libs/surfaceflinger/CPUGauge.h
@@ -0,0 +1,74 @@
+/*
+ * 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
new file mode 100644
index 0000000..f14d7e9
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -0,0 +1,353 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <cutils/properties.h>
+
+#include <utils/Log.h>
+
+#include <ui/EGLDisplaySurface.h>
+
+#include <GLES/gl.h>
+#include <EGL/eglext.h>
+
+
+#include "DisplayHardware/DisplayHardware.h"
+
+#include <hardware/copybit.h>
+#include <hardware/overlay.h>
+
+using namespace android;
+
+static __attribute__((noinline))
+const char *egl_strerror(EGLint err)
+{
+    switch (err){
+        case EGL_SUCCESS:           return "EGL_SUCCESS";
+        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
+        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
+        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
+        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
+        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
+        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
+        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
+        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
+        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
+        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
+        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
+        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
+        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
+        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
+        default: return "UNKNOWN";
+    }
+}
+
+static __attribute__((noinline))
+void checkGLErrors()
+{
+    GLenum error = glGetError();
+    if (error != GL_NO_ERROR)
+        LOGE("GL error 0x%04x", int(error));
+}
+
+static __attribute__((noinline))
+void checkEGLErrors(const char* token)
+{
+    EGLint error = eglGetError();
+    // GLESonGL seems to be returning 0 when there is no errors?
+    if (error && error != EGL_SUCCESS)
+        LOGE("%s error 0x%04x (%s)",
+                token, int(error), egl_strerror(error));
+}
+
+
+/*
+ * Initialize the display to the specified values.
+ *
+ */
+
+DisplayHardware::DisplayHardware(
+        const sp<SurfaceFlinger>& flinger,
+        uint32_t dpy)
+    : DisplayHardwareBase(flinger, dpy)
+{
+    init(dpy);
+}
+
+DisplayHardware::~DisplayHardware()
+{
+    fini();
+}
+
+float DisplayHardware::getDpiX() const          { return mDpiX; }
+float DisplayHardware::getDpiY() const          { return mDpiY; }
+float DisplayHardware::getDensity() const       { return mDensity; }
+float DisplayHardware::getRefreshRate() const   { return mRefreshRate; }
+int DisplayHardware::getWidth() const           { return mWidth; }
+int DisplayHardware::getHeight() const          { return mHeight; }
+PixelFormat DisplayHardware::getFormat() const  { return mFormat; }
+
+void DisplayHardware::init(uint32_t dpy)
+{
+    // initialize EGL
+    const EGLint attribs[] = {
+            EGL_RED_SIZE,       5,
+            EGL_GREEN_SIZE,     6,
+            EGL_BLUE_SIZE,      5,
+            EGL_DEPTH_SIZE,     0,
+            EGL_NONE
+    };
+    EGLint w, h, dummy;
+    EGLint numConfigs, n;
+    EGLConfig config;
+    EGLSurface surface;
+    EGLContext context;
+    mFlags = 0;
+
+    // TODO: all the extensions below should be queried through
+    // eglGetProcAddress().
+
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglInitialize(display, NULL, NULL);
+    eglGetConfigs(display, NULL, 0, &numConfigs);
+    eglChooseConfig(display, attribs, &config, 1, &n);
+
+    /*
+     * Gather EGL extensions
+     */
+
+    const char* const egl_extensions = eglQueryString(
+            display, EGL_EXTENSIONS);
+    
+    LOGI("EGL informations:");
+    LOGI("# of configs : %d", numConfigs);
+    LOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
+    LOGI("version   : %s", eglQueryString(display, EGL_VERSION));
+    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 (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
+        if (dummy == EGL_SLOW_CONFIG)
+            mFlags |= SLOW_CONFIG;
+    }
+
+    /*
+     * Create our main surface
+     */
+
+    mDisplaySurface = new EGLDisplaySurface();
+
+    surface = eglCreateWindowSurface(display, config, mDisplaySurface.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;
+    }
+    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 
+    
+    
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
+        LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
+        strcpy(property, "160");
+    }
+    mDensity = atoi(property) * (1.0f/160.0f);
+
+
+    /*
+     * Create our OpenGL ES context
+     */
+    
+    context = eglCreateContext(display, config, NULL, NULL);
+    //checkEGLErrors("eglCreateContext");
+    
+    eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
+    
+    
+    /*
+     * Gather OpenGL ES extensions
+     */
+
+    eglMakeCurrent(display, surface, surface, context);
+    const char* const  gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
+    LOGI("OpenGL informations:");
+    LOGI("vendor    : %s", glGetString(GL_VENDOR));
+    LOGI("renderer  : %s", glGetString(GL_RENDERER));
+    LOGI("version   : %s", glGetString(GL_VERSION));
+    LOGI("extensions: %s", gl_extensions);
+
+    if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
+        mFlags |= NPOT_EXTENSION;
+    }
+    if (strstr(gl_extensions, "GL_OES_draw_texture")) {
+        mFlags |= DRAW_TEXTURE_EXTENSION;
+    }
+    if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) {
+        mFlags |= DIRECT_TEXTURE;
+    }
+
+    // Unbind the context from this thread
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+    mDisplay = display;
+    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);
+    }
+}
+
+/*
+ * Clean up.  Throw out our local state.
+ *
+ * (It's entirely possible we'll never get here, since this is meant
+ * for real hardware, which doesn't restart.)
+ */
+
+void DisplayHardware::fini()
+{
+    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(mDisplay);
+    copybit_close(mBlitEngine);
+    overlay_control_close(mOverlayEngine);
+}
+
+void DisplayHardware::releaseScreen() const
+{
+    DisplayHardwareBase::releaseScreen();
+}
+
+void DisplayHardware::acquireScreen() const
+{
+    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();
+}
+
+/*
+ * "Flip" the front and back buffers.
+ */
+
+void DisplayHardware::flip(const Region& dirty) const
+{
+    checkGLErrors();
+
+    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_EXTENSION) {
+        const Rect& b(newDirty.bounds());
+        mDisplaySurface->setSwapRectangle(
+                b.left, b.top, b.width(), b.height());
+    }
+
+    eglSwapBuffers(dpy, surface);
+    checkEGLErrors("eglSwapBuffers");
+
+    // for debugging
+    //glClearColor(1,0,0,0);
+    //glClear(GL_COLOR_BUFFER_BIT);
+}
+
+uint32_t DisplayHardware::getFlags() const
+{
+    return mFlags;
+}
+
+void DisplayHardware::makeCurrent() const
+{
+    eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
+}
+
+void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
+    mDisplaySurface->copyFrontToImage(front);
+}
+
+void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
+    mDisplaySurface->copyBackToImage(front);
+}
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
new file mode 100644
index 0000000..550a4d1
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -0,0 +1,113 @@
+/*
+ * 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_DISPLAY_HARDWARE_H
+#define ANDROID_DISPLAY_HARDWARE_H
+
+#include <stdlib.h>
+
+#include <ui/PixelFormat.h>
+#include <ui/Region.h>
+
+#include <EGL/egl.h>
+
+#include "DisplayHardware/DisplayHardwareBase.h"
+
+struct overlay_control_device_t;
+struct copybit_device_t;
+struct copybit_image_t;
+struct copybit_t;
+
+namespace android {
+
+class EGLDisplaySurface;
+
+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
+    };
+
+    DisplayHardware(
+            const sp<SurfaceFlinger>& flinger,
+            uint32_t displayIndex);
+
+    ~DisplayHardware();
+
+    void releaseScreen() const;
+    void acquireScreen() const;
+
+    // Flip the front and back buffers if the back buffer is "dirty".  Might
+    // be instantaneous, might involve copying the frame buffer around.
+    void flip(const Region& dirty) const;
+
+    float       getDpiX() const;
+    float       getDpiY() const;
+    float       getRefreshRate() const;
+    float       getDensity() const;
+    int         getWidth() const;
+    int         getHeight() const;
+    PixelFormat getFormat() const;
+    uint32_t    getFlags() const;
+    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;
+    void copyBackToImage(const copybit_image_t& front) const;
+       
+    Rect bounds() const {
+        return Rect(mWidth, mHeight);
+    }
+
+private:
+    void init(uint32_t displayIndex) __attribute__((noinline));
+    void fini() __attribute__((noinline));
+
+    EGLDisplay      mDisplay;
+    EGLSurface      mSurface;
+    EGLContext      mContext;
+    EGLConfig       mConfig;
+    float           mDpiX;
+    float           mDpiY;
+    float           mRefreshRate;
+    float           mDensity;
+    int             mWidth;
+    int             mHeight;
+    PixelFormat     mFormat;
+    uint32_t        mFlags;
+    mutable Region  mDirty;
+    sp<EGLDisplaySurface> mDisplaySurface;
+    copybit_device_t*     mBlitEngine;
+    overlay_control_device_t* mOverlayEngine;
+};
+
+}; // namespace android
+
+#endif // ANDROID_DISPLAY_HARDWARE_H
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
new file mode 100644
index 0000000..f75e5c2
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -0,0 +1,403 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+
+#include <linux/unistd.h>
+
+#include <utils/Log.h>
+
+#include "DisplayHardware/DisplayHardwareBase.h"
+#include "SurfaceFlinger.h"
+
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+// ----------------------------------------------------------------------------
+namespace android {
+
+static char const * kSleepFileName = "/sys/power/wait_for_fb_sleep";
+static char const * kWakeFileName = "/sys/power/wait_for_fb_wake";
+static char const * const kOldSleepFileName = "/sys/android_power/wait_for_fb_sleep";
+static char const * const kOldWakeFileName = "/sys/android_power/wait_for_fb_wake";
+
+// This dir exists if the framebuffer console is present, either built into
+// the kernel or loaded as a module.
+static char const * const kFbconSysDir = "/sys/class/graphics/fbcon";
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayEventThreadBase::DisplayEventThreadBase(
+        const sp<SurfaceFlinger>& flinger)
+    : Thread(false), mFlinger(flinger) {
+}
+
+DisplayHardwareBase::DisplayEventThreadBase::~DisplayEventThreadBase() {
+}
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayEventThread::DisplayEventThread(
+        const sp<SurfaceFlinger>& flinger)
+    : DisplayEventThreadBase(flinger)
+{
+}
+
+DisplayHardwareBase::DisplayEventThread::~DisplayEventThread()
+{
+}
+
+bool DisplayHardwareBase::DisplayEventThread::threadLoop()
+{
+    int err = 0;
+    char buf;
+    int fd;
+
+    fd = open(kSleepFileName, O_RDONLY, 0);
+    do {
+      err = read(fd, &buf, 1);
+    } while (err < 0 && errno == EINTR);
+    close(fd);
+    LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
+    if (err >= 0) {
+        sp<SurfaceFlinger> flinger = mFlinger.promote();
+        LOGD("About to give-up screen, flinger = %p", flinger.get());
+        if (flinger != 0) {
+            mBarrier.close();
+            flinger->screenReleased(0);
+            mBarrier.wait();
+        }
+    }
+    fd = open(kWakeFileName, O_RDONLY, 0);
+    do {
+      err = read(fd, &buf, 1);
+    } while (err < 0 && errno == EINTR);
+    close(fd);
+    LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
+    if (err >= 0) {
+        sp<SurfaceFlinger> flinger = mFlinger.promote();
+        LOGD("Screen about to return, flinger = %p", flinger.get());
+        if (flinger != 0)
+            flinger->screenAcquired(0);
+    }
+    return true;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const
+{
+    mBarrier.open();
+    return NO_ERROR;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::readyToRun()
+{
+    if (access(kSleepFileName, R_OK) || access(kWakeFileName, R_OK)) {
+        if (access(kOldSleepFileName, R_OK) || access(kOldWakeFileName, R_OK)) {
+            LOGE("Couldn't open %s or %s", kSleepFileName, kWakeFileName);
+            return NO_INIT;
+        }
+        kSleepFileName = kOldSleepFileName;
+        kWakeFileName = kOldWakeFileName;
+    }
+    return NO_ERROR;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::initCheck() const
+{
+    return (((access(kSleepFileName, R_OK) == 0 &&
+            access(kWakeFileName, R_OK) == 0) ||
+            (access(kOldSleepFileName, R_OK) == 0 &&
+            access(kOldWakeFileName, R_OK) == 0)) &&
+            access(kFbconSysDir, F_OK) != 0) ? NO_ERROR : NO_INIT;
+}
+
+// ----------------------------------------------------------------------------
+
+pid_t DisplayHardwareBase::ConsoleManagerThread::sSignalCatcherPid = 0;
+
+DisplayHardwareBase::ConsoleManagerThread::ConsoleManagerThread(
+        const sp<SurfaceFlinger>& flinger)
+    : DisplayEventThreadBase(flinger), consoleFd(-1)
+{   
+    sSignalCatcherPid = 0;
+
+    // create a new console
+    char const * const ttydev = "/dev/tty0";
+    int fd = open(ttydev, O_RDWR | O_SYNC);
+    if (fd<0) {
+        LOGE("Can't open %s", ttydev);
+        this->consoleFd = -errno;
+        return;
+    }
+
+    // to make sure that we are in text mode
+    int res = ioctl(fd, KDSETMODE, (void*) KD_TEXT);
+    if (res<0) {
+        LOGE("ioctl(%d, KDSETMODE, ...) failed, res %d (%s)",
+                fd, res, strerror(errno));
+    }
+    
+    // get the current console
+    struct vt_stat vs;
+    res = ioctl(fd, VT_GETSTATE, &vs);
+    if (res<0) {
+        LOGE("ioctl(%d, VT_GETSTATE, ...) failed, res %d (%s)",
+                fd, res, strerror(errno));
+        this->consoleFd = -errno;
+        return;
+    }
+
+    // switch to console 7 (which is what X normaly uses)
+    int vtnum = 7;
+    do {
+        res = ioctl(fd, VT_ACTIVATE, (void*)vtnum);
+    } while(res < 0 && errno == EINTR);
+    if (res<0) {
+        LOGE("ioctl(%d, VT_ACTIVATE, ...) failed, %d (%s) for %d",
+                fd, errno, strerror(errno), vtnum);
+        this->consoleFd = -errno;
+        return;
+    }
+
+    do {
+        res = ioctl(fd, VT_WAITACTIVE, (void*)vtnum);
+    } while(res < 0 && errno == EINTR);
+    if (res<0) {
+        LOGE("ioctl(%d, VT_WAITACTIVE, ...) failed, %d %d %s for %d",
+                fd, res, errno, strerror(errno), vtnum);
+        this->consoleFd = -errno;
+        return;
+    }
+
+    // open the new console
+    close(fd);
+    fd = open(ttydev, O_RDWR | O_SYNC);
+    if (fd<0) {
+        LOGE("Can't open new console %s", ttydev);
+        this->consoleFd = -errno;
+        return;
+    }
+
+    /* disable console line buffer, echo, ... */
+    struct termios ttyarg;
+    ioctl(fd, TCGETS , &ttyarg);
+    ttyarg.c_iflag = 0;
+    ttyarg.c_lflag = 0;
+    ioctl(fd, TCSETS , &ttyarg);
+
+    // set up signals so we're notified when the console changes
+    // we can't use SIGUSR1 because it's used by the java-vm
+    vm.mode = VT_PROCESS;
+    vm.waitv = 0;
+    vm.relsig = SIGUSR2;
+    vm.acqsig = SIGUNUSED;
+    vm.frsig = 0;
+
+    struct sigaction act;
+    sigemptyset(&act.sa_mask);
+    act.sa_handler = sigHandler;
+    act.sa_flags = 0;
+    sigaction(vm.relsig, &act, NULL);
+
+    sigemptyset(&act.sa_mask);
+    act.sa_handler = sigHandler;
+    act.sa_flags = 0;
+    sigaction(vm.acqsig, &act, NULL);
+
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, vm.relsig);
+    sigaddset(&mask, vm.acqsig);
+    sigprocmask(SIG_BLOCK, &mask, NULL);
+
+    // switch to graphic mode
+    res = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS);
+    LOGW_IF(res<0,
+            "ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, res %d", fd, res);
+
+    this->prev_vt_num = vs.v_active;
+    this->vt_num = vtnum;
+    this->consoleFd = fd;
+}
+
+DisplayHardwareBase::ConsoleManagerThread::~ConsoleManagerThread()
+{   
+    if (this->consoleFd >= 0) {
+        int fd = this->consoleFd;
+        int prev_vt_num = this->prev_vt_num;
+        int res;
+        ioctl(fd, KDSETMODE, (void*)KD_TEXT);
+        do {
+            res = ioctl(fd, VT_ACTIVATE, (void*)prev_vt_num);
+        } while(res < 0 && errno == EINTR);
+        do {
+            res = ioctl(fd, VT_WAITACTIVE, (void*)prev_vt_num);
+        } while(res < 0 && errno == EINTR);
+        close(fd);    
+        char const * const ttydev = "/dev/tty0";
+        fd = open(ttydev, O_RDWR | O_SYNC);
+        ioctl(fd, VT_DISALLOCATE, 0);
+        close(fd);
+    }
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::readyToRun()
+{
+    if (this->consoleFd >= 0) {
+        sSignalCatcherPid = gettid();
+        
+        sigset_t mask;
+        sigemptyset(&mask);
+        sigaddset(&mask, vm.relsig);
+        sigaddset(&mask, vm.acqsig);
+        sigprocmask(SIG_BLOCK, &mask, NULL);
+
+        int res = ioctl(this->consoleFd, VT_SETMODE, &vm);
+        if (res<0) {
+            LOGE("ioctl(%d, VT_SETMODE, ...) failed, %d (%s)",
+                    this->consoleFd, errno, strerror(errno));
+        }
+        return NO_ERROR;
+    }
+    return this->consoleFd;
+}
+
+void DisplayHardwareBase::ConsoleManagerThread::requestExit()
+{
+    Thread::requestExit();
+    if (sSignalCatcherPid != 0) {
+        // wake the thread up
+        kill(sSignalCatcherPid, SIGINT);
+        // wait for it...
+    }
+}
+
+void DisplayHardwareBase::ConsoleManagerThread::sigHandler(int sig)
+{
+    // resend the signal to our signal catcher thread
+    LOGW("received signal %d in thread %d, resending to %d",
+            sig, gettid(), sSignalCatcherPid);
+
+    // we absolutely need the delays below because without them
+    // our main thread never gets a chance to handle the signal.
+    usleep(10000);
+    kill(sSignalCatcherPid, sig);
+    usleep(10000);
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::releaseScreen() const
+{
+    int fd = this->consoleFd;
+    int err = ioctl(fd, VT_RELDISP, (void*)1);
+    LOGE_IF(err<0, "ioctl(%d, VT_RELDISP, 1) failed %d (%s)",
+        fd, errno, strerror(errno));
+    return (err<0) ? (-errno) : status_t(NO_ERROR);
+}
+
+bool DisplayHardwareBase::ConsoleManagerThread::threadLoop()
+{
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, vm.relsig);
+    sigaddset(&mask, vm.acqsig);
+
+    int sig = 0;
+    sigwait(&mask, &sig);
+
+    if (sig == vm.relsig) {
+        sp<SurfaceFlinger> flinger = mFlinger.promote();
+        //LOGD("About to give-up screen, flinger = %p", flinger.get());
+        if (flinger != 0)
+            flinger->screenReleased(0);
+    } else if (sig == vm.acqsig) {
+        sp<SurfaceFlinger> flinger = mFlinger.promote();
+        //LOGD("Screen about to return, flinger = %p", flinger.get());
+        if (flinger != 0) 
+            flinger->screenAcquired(0);
+    }
+    
+    return true;
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::initCheck() const
+{
+    return consoleFd >= 0 ? NO_ERROR : NO_INIT;
+}
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
+        uint32_t displayIndex) 
+    : mCanDraw(true)
+{
+    mDisplayEventThread = new DisplayEventThread(flinger);
+    if (mDisplayEventThread->initCheck() != NO_ERROR) {
+        // fall-back on the console
+        mDisplayEventThread = new ConsoleManagerThread(flinger);
+    }
+}
+
+DisplayHardwareBase::~DisplayHardwareBase()
+{
+    // request exit
+    mDisplayEventThread->requestExitAndWait();
+}
+
+
+bool DisplayHardwareBase::canDraw() const
+{
+    return mCanDraw;
+}
+
+void DisplayHardwareBase::releaseScreen() const
+{
+    status_t err = mDisplayEventThread->releaseScreen();
+    if (err >= 0) {
+        //LOGD("screen given-up");
+        mCanDraw = false;
+    }
+}
+
+void DisplayHardwareBase::acquireScreen() const
+{
+    status_t err = mDisplayEventThread->acquireScreen();
+    if (err >= 0) {
+        //LOGD("screen returned");
+        mCanDraw = true;
+    }
+}
+
+}; // namespace android
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
new file mode 100644
index 0000000..8369bb8
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -0,0 +1,96 @@
+/*
+ * 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_DISPLAY_HARDWARE_BASE_H
+#define ANDROID_DISPLAY_HARDWARE_BASE_H
+
+#include <stdint.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include "Barrier.h"
+
+namespace android {
+
+class SurfaceFlinger; 
+
+class DisplayHardwareBase
+{
+public:
+                DisplayHardwareBase(
+                        const sp<SurfaceFlinger>& flinger,
+                        uint32_t displayIndex);
+
+                ~DisplayHardwareBase();
+
+    // console managment
+    void releaseScreen() const;
+    void acquireScreen() const;
+    bool canDraw() const;
+
+private:
+    class DisplayEventThreadBase : public Thread {
+    protected:
+        wp<SurfaceFlinger> mFlinger;
+    public:
+        DisplayEventThreadBase(const sp<SurfaceFlinger>& flinger);
+        virtual ~DisplayEventThreadBase();
+        virtual void onFirstRef() {
+            run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
+        }
+        virtual status_t acquireScreen() const { return NO_ERROR; };
+        virtual status_t releaseScreen() const { return NO_ERROR; };
+        virtual status_t initCheck() const = 0;
+    };
+
+    class DisplayEventThread : public DisplayEventThreadBase 
+    {
+        mutable Barrier mBarrier;
+    public:
+                DisplayEventThread(const sp<SurfaceFlinger>& flinger);
+        virtual ~DisplayEventThread();
+        virtual bool threadLoop();
+        virtual status_t readyToRun();
+        virtual status_t releaseScreen() const;
+        virtual status_t initCheck() const;
+    };
+
+    class ConsoleManagerThread : public DisplayEventThreadBase 
+    {
+        int consoleFd;
+        int vt_num;
+        int prev_vt_num;
+        vt_mode vm;
+        static void sigHandler(int sig);
+        static pid_t sSignalCatcherPid;
+    public:
+                ConsoleManagerThread(const sp<SurfaceFlinger>& flinger);
+        virtual ~ConsoleManagerThread();
+        virtual bool threadLoop();
+        virtual status_t readyToRun();
+        virtual void requestExit();
+        virtual status_t releaseScreen() const;
+        virtual status_t initCheck() const;
+    };
+
+    sp<DisplayEventThreadBase>  mDisplayEventThread;
+    mutable int                 mCanDraw;
+};
+
+}; // namespace android
+
+#endif // ANDROID_DISPLAY_HARDWARE_BASE_H
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
new file mode 100644
index 0000000..eb75f99
--- /dev/null
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
@@ -0,0 +1,581 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "SurfaceFlinger"
+
+#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/IBinder.h>
+#include <utils/MemoryDealer.h>
+#include <utils/MemoryBase.h>
+#include <utils/MemoryHeapPmem.h>
+#include <utils/MemoryHeapBase.h>
+#include <utils/IPCThreadState.h>
+#include <utils/StopWatch.h>
+
+#include <ui/ISurfaceComposer.h>
+
+#include "VRamHeap.h"
+#include "GPUHardware.h"
+
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#endif
+
+#include "GPUHardware/GPUHardware.h"
+
+
+/* 
+ * Manage the GPU. This implementation is very specific to the G1.
+ * There are no abstraction here. 
+ * 
+ * All this code will soon go-away and be replaced by a new architecture
+ * for managing graphics accelerators.
+ * 
+ * In the meantime, it is conceptually possible to instantiate a
+ * GPUHardwareInterface for another GPU (see GPUFactory at the bottom
+ * of this file); practically... doubtful.
+ * 
+ */
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class GPUClientHeap;
+class GPUAreaHeap;
+
+class GPUHardware : public GPUHardwareInterface, public IBinder::DeathRecipient
+{
+public:
+    static const int GPU_RESERVED_SIZE;
+    static const int GPUR_SIZE;
+
+            GPUHardware();
+    virtual ~GPUHardware();
+    
+    virtual void revoke(int pid);
+    virtual sp<MemoryDealer> request(int pid);
+    virtual status_t request(int pid, 
+            const sp<IGPUCallback>& callback,
+            ISurfaceComposer::gpu_info_t* gpu);
+
+    virtual status_t friendlyRevoke();
+    virtual void unconditionalRevoke();
+    
+    virtual pid_t getOwner() const { return mOwner; }
+
+    // used for debugging only...
+    virtual sp<SimpleBestFitAllocator> getAllocator() const;
+
+private:
+    
+    
+    enum {
+        NO_OWNER = -1,
+    };
+        
+    struct GPUArea {
+        sp<GPUAreaHeap>     heap;
+        sp<MemoryHeapPmem>  clientHeap;
+        sp<IMemory> map();
+    };
+    
+    struct Client {
+        pid_t       pid;
+        GPUArea     smi;
+        GPUArea     ebi;
+        GPUArea     reg;
+        void createClientHeaps();
+        void revokeAllHeaps();
+    };
+    
+    Client& getClientLocked(pid_t pid);
+    status_t requestLocked(int pid);
+    void releaseLocked();
+    void takeBackGPULocked();
+    void registerCallbackLocked(const sp<IGPUCallback>& callback,
+            Client& client);
+
+    virtual void binderDied(const wp<IBinder>& who);
+
+    mutable Mutex           mLock;
+    sp<GPUAreaHeap>         mSMIHeap;
+    sp<GPUAreaHeap>         mEBIHeap;
+    sp<GPUAreaHeap>         mREGHeap;
+
+    KeyedVector<pid_t, Client> mClients;
+    DefaultKeyedVector< wp<IBinder>, pid_t > mRegisteredClients;
+    
+    pid_t                   mOwner;
+
+    sp<MemoryDealer>        mCurrentAllocator;
+    sp<IGPUCallback>        mCallback;
+    
+    sp<SimpleBestFitAllocator>  mAllocator;
+
+    Condition               mCondition;
+};
+
+// size reserved for GPU surfaces
+// 1200 KB fits exactly:
+//  - two 320*480 16-bits double-buffered surfaces
+//  - one 320*480 32-bits double-buffered surface
+//  - one 320*240 16-bits double-buffered, 4x anti-aliased surface
+const int GPUHardware::GPU_RESERVED_SIZE  = 1200 * 1024;
+const int GPUHardware::GPUR_SIZE          = 1 * 1024 * 1024;
+
+// ---------------------------------------------------------------------------
+
+/* 
+ * GPUHandle is a special IMemory given to the client. It represents their
+ * handle to the GPU. Once they give it up, they loose GPU access, or if
+ * they explicitly revoke their access through the binder code 1000.
+ * In both cases, this triggers a callback to revoke()
+ * first, and then actually powers down the chip.
+ * 
+ * In the case of a misbehaving app, GPUHardware can ask for an immediate
+ * release of the GPU to the target process which should answer by calling
+ * code 1000 on GPUHandle. If it doesn't in a timely manner, the GPU will
+ * be revoked from under their feet.
+ * 
+ * We should never hold a strong reference on GPUHandle. In practice this
+ * shouldn't be a big issue though because clients should use code 1000 and
+ * not rely on the dtor being called.
+ * 
+ */
+
+class GPUClientHeap : public MemoryHeapPmem
+{
+public:
+    GPUClientHeap(const wp<GPUHardware>& gpu, 
+            const sp<MemoryHeapBase>& heap)
+        :  MemoryHeapPmem(heap), mGPU(gpu) { }
+protected:
+    wp<GPUHardware> mGPU;
+};
+
+class GPUAreaHeap : public MemoryHeapBase
+{
+public:
+    GPUAreaHeap(const wp<GPUHardware>& gpu,
+            const char* const vram, size_t size=0, size_t reserved=0)
+    : MemoryHeapBase(vram, size), mGPU(gpu) { 
+        if (base() != MAP_FAILED) {
+            if (reserved == 0)
+                reserved = virtualSize();
+            mAllocator = new SimpleBestFitAllocator(reserved);
+        }
+    }
+    virtual sp<MemoryHeapPmem> createClientHeap() {
+        sp<MemoryHeapBase> parentHeap(this);
+        return new GPUClientHeap(mGPU, parentHeap);
+    }
+    virtual const sp<SimpleBestFitAllocator>& getAllocator() const {
+        return mAllocator; 
+    }
+private:
+    sp<SimpleBestFitAllocator>  mAllocator;
+protected:
+    wp<GPUHardware> mGPU;
+};
+
+class GPURegisterHeap : public GPUAreaHeap
+{
+public:
+    GPURegisterHeap(const sp<GPUHardware>& gpu)
+        : GPUAreaHeap(gpu, "/dev/hw3d", GPUHardware::GPUR_SIZE) { }
+    virtual sp<MemoryHeapPmem> createClientHeap() {
+        sp<MemoryHeapBase> parentHeap(this);
+        return new MemoryHeapRegs(mGPU, parentHeap);
+    }
+private:
+    class MemoryHeapRegs : public GPUClientHeap  {
+    public:
+        MemoryHeapRegs(const wp<GPUHardware>& gpu, 
+             const sp<MemoryHeapBase>& heap)
+            : GPUClientHeap(gpu, heap) { }
+        sp<MemoryHeapPmem::MemoryPmem> createMemory(size_t offset, size_t size);
+        virtual void revoke();
+    private:
+        class GPUHandle : public MemoryHeapPmem::MemoryPmem {
+        public:
+            GPUHandle(const sp<GPUHardware>& gpu,
+                    const sp<MemoryHeapPmem>& heap)
+                : MemoryHeapPmem::MemoryPmem(heap), 
+                  mGPU(gpu), mOwner(gpu->getOwner()) { }
+            virtual ~GPUHandle();
+            virtual sp<IMemoryHeap> getMemory(
+                    ssize_t* offset, size_t* size) const;
+            virtual void revoke() { };
+            virtual status_t onTransact(
+                    uint32_t code, const Parcel& data, 
+                    Parcel* reply, uint32_t flags);
+        private:
+            void revokeNotification();
+            wp<GPUHardware> mGPU;
+            pid_t mOwner;
+        };
+    };
+};
+
+GPURegisterHeap::MemoryHeapRegs::GPUHandle::~GPUHandle() { 
+    //LOGD("GPUHandle %p released, revoking GPU", this);
+    revokeNotification(); 
+}
+void GPURegisterHeap::MemoryHeapRegs::GPUHandle::revokeNotification()  {
+    sp<GPUHardware> hw(mGPU.promote());
+    if (hw != 0) {
+        hw->revoke(mOwner);
+    }
+}
+sp<IMemoryHeap> GPURegisterHeap::MemoryHeapRegs::GPUHandle::getMemory(
+        ssize_t* offset, size_t* size) const
+{
+    sp<MemoryHeapPmem> heap = getHeap();
+    if (offset) *offset = 0;
+    if (size)   *size = heap !=0 ? heap->virtualSize() : 0;
+    return heap;
+}
+status_t GPURegisterHeap::MemoryHeapRegs::GPUHandle::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    status_t err = BnMemory::onTransact(code, data, reply, flags);
+    if (err == UNKNOWN_TRANSACTION && code == 1000) {
+        int callingPid = IPCThreadState::self()->getCallingPid();
+        //LOGD("pid %d voluntarily revoking gpu", callingPid);
+        if (callingPid == mOwner) {
+            revokeNotification();
+            // we've revoked the GPU, don't do it again later when we
+            // are destroyed.
+            mGPU.clear();
+        } else {
+            LOGW("%d revoking someone else's gpu? (owner=%d)",
+                    callingPid, mOwner);            
+        }
+        err = NO_ERROR;
+    }
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+
+
+sp<MemoryHeapPmem::MemoryPmem> GPURegisterHeap::MemoryHeapRegs::createMemory(
+        size_t offset, size_t size)
+{
+    sp<GPUHandle> memory;
+    sp<GPUHardware> gpu = mGPU.promote();
+    if (heapID()>0 && gpu!=0) {
+#if HAVE_ANDROID_OS
+        /* this is where the GPU is powered on and the registers are mapped
+         * in the client */
+        //LOGD("ioctl(HW3D_GRANT_GPU)");
+        int err = ioctl(heapID(), HW3D_GRANT_GPU, base());
+        if (err) {
+            // it can happen if the master heap has been closed already
+            // in which case the GPU already is revoked (app crash for
+            // instance).
+            LOGW("HW3D_GRANT_GPU failed (%s), mFD=%d, base=%p",
+                    strerror(errno), heapID(), base());
+        }
+        memory = new GPUHandle(gpu, this);
+#endif
+    }
+    return memory;
+}
+
+void GPURegisterHeap::MemoryHeapRegs::revoke() 
+{
+    MemoryHeapPmem::revoke();
+#if HAVE_ANDROID_OS
+    if (heapID() > 0) {
+        //LOGD("ioctl(HW3D_REVOKE_GPU)");
+        int err = ioctl(heapID(), HW3D_REVOKE_GPU, base());
+        LOGE_IF(err, "HW3D_REVOKE_GPU failed (%s), mFD=%d, base=%p",
+                strerror(errno), heapID(), base());
+    }
+#endif
+}
+
+/*****************************************************************************/
+
+GPUHardware::GPUHardware()
+    : mOwner(NO_OWNER)
+{
+}
+
+GPUHardware::~GPUHardware()
+{
+}
+
+status_t GPUHardware::requestLocked(int pid)
+{
+    const int self_pid = getpid();
+    if (pid == self_pid) {
+        // can't use GPU from surfaceflinger's process
+        return PERMISSION_DENIED;
+    }
+
+    if (mOwner != pid) {
+        if (mREGHeap != 0) {
+            if (mOwner != NO_OWNER) {
+                // someone already has the gpu.
+                takeBackGPULocked();
+                releaseLocked();
+            }
+        } else {
+            // first time, initialize the stuff.
+            if (mSMIHeap == 0)
+                mSMIHeap = new GPUAreaHeap(this, "/dev/pmem_gpu0");
+            if (mEBIHeap == 0)
+                mEBIHeap = new GPUAreaHeap(this, 
+                        "/dev/pmem_gpu1", 0, GPU_RESERVED_SIZE);
+            mREGHeap = new GPURegisterHeap(this);
+            mAllocator = mEBIHeap->getAllocator();
+            if (mAllocator == NULL) {
+                // something went terribly wrong.
+                mSMIHeap.clear();
+                mEBIHeap.clear();
+                mREGHeap.clear();
+                return INVALID_OPERATION;
+            }
+        }
+        Client& client = getClientLocked(pid);
+        mCurrentAllocator = new MemoryDealer(client.ebi.clientHeap, mAllocator);
+        mOwner = pid;
+    }
+    return NO_ERROR;
+}
+
+sp<MemoryDealer> GPUHardware::request(int pid)
+{
+    sp<MemoryDealer> dealer;
+    Mutex::Autolock _l(mLock);
+    Client* client;
+    LOGD("pid %d requesting gpu surface (current owner = %d)", pid, mOwner);
+    if (requestLocked(pid) == NO_ERROR) {
+        dealer = mCurrentAllocator;
+        LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner);
+    }
+    return dealer;
+}
+
+status_t GPUHardware::request(int pid, const sp<IGPUCallback>& callback,
+        ISurfaceComposer::gpu_info_t* gpu)
+{
+    if (callback == 0)
+        return BAD_VALUE;
+
+    sp<IMemory> gpuHandle;
+    LOGD("pid %d requesting gpu core (owner = %d)", pid, mOwner);
+    Mutex::Autolock _l(mLock);
+    status_t err = requestLocked(pid);
+    if (err == NO_ERROR) {
+        // it's guaranteed to be there, be construction
+        Client& client = mClients.editValueFor(pid);
+        registerCallbackLocked(callback, client);
+        gpu->count = 2;
+        gpu->regions[0].region = client.smi.map();
+        gpu->regions[1].region = client.ebi.map();
+        gpu->regs              = client.reg.map();
+        gpu->regions[0].reserved = 0;
+        gpu->regions[1].reserved = GPU_RESERVED_SIZE;
+        if (gpu->regs != 0) {
+            //LOGD("gpu core granted to pid %d, handle base=%p",
+            //        mOwner, gpu->regs->pointer());
+        }
+        mCallback = callback;
+    } else {
+        LOGW("couldn't grant gpu core to pid %d", pid);
+    }
+    return err;
+}
+
+void GPUHardware::revoke(int pid)
+{
+    Mutex::Autolock _l(mLock);
+    if (mOwner > 0) {
+        if (pid != mOwner) {
+            LOGW("GPU owned by %d, revoke from %d", mOwner, pid);
+            return;
+        }
+        //LOGD("revoke pid=%d, owner=%d", pid, mOwner);
+        // mOwner could be <0 if the same process acquired the GPU
+        // several times without releasing it first.
+        mCondition.signal();
+        releaseLocked();
+    }
+}
+
+status_t GPUHardware::friendlyRevoke()
+{
+    Mutex::Autolock _l(mLock);
+    //LOGD("friendlyRevoke owner=%d", mOwner);
+    takeBackGPULocked();
+    releaseLocked();
+    return NO_ERROR;
+}
+
+void GPUHardware::takeBackGPULocked()
+{
+    sp<IGPUCallback> callback = mCallback;
+    mCallback.clear();
+    if (callback != 0) {
+        callback->gpuLost(); // one-way
+        mCondition.waitRelative(mLock, ms2ns(250));
+    }
+}
+
+void GPUHardware::releaseLocked()
+{
+    //LOGD("revoking gpu from pid %d", mOwner);
+    if (mOwner != NO_OWNER) {
+        // this may fail because the client might have died, and have
+        // been removed from the list.
+        ssize_t index = mClients.indexOfKey(mOwner);
+        if (index >= 0) {
+            Client& client(mClients.editValueAt(index));
+            client.revokeAllHeaps();
+        }
+        mOwner = NO_OWNER;
+        mCurrentAllocator.clear();
+        mCallback.clear();
+    }
+}
+
+GPUHardware::Client& GPUHardware::getClientLocked(pid_t pid)
+{
+    ssize_t index = mClients.indexOfKey(pid);
+    if (index < 0) {
+        Client client;
+        client.pid = pid;
+        client.smi.heap = mSMIHeap;
+        client.ebi.heap = mEBIHeap;
+        client.reg.heap = mREGHeap;
+        index = mClients.add(pid, client);
+    }
+    Client& client(mClients.editValueAt(index));
+    client.createClientHeaps();
+    return client;
+}
+
+// ----------------------------------------------------------------------------
+// for debugging / testing ...
+
+sp<SimpleBestFitAllocator> GPUHardware::getAllocator() const {
+    Mutex::Autolock _l(mLock);
+    return mAllocator;
+}
+
+void GPUHardware::unconditionalRevoke()
+{
+    Mutex::Autolock _l(mLock);
+    releaseLocked();
+}
+
+// ---------------------------------------------------------------------------
+
+sp<IMemory> GPUHardware::GPUArea::map() {
+    sp<IMemory> memory;
+    if (clientHeap != 0 && heap != 0) {
+        memory = clientHeap->mapMemory(0, heap->virtualSize());
+    }
+    return memory;
+}
+
+void GPUHardware::Client::createClientHeaps() 
+{
+    if (smi.clientHeap == 0)
+        smi.clientHeap = smi.heap->createClientHeap();
+    if (ebi.clientHeap == 0)
+        ebi.clientHeap = ebi.heap->createClientHeap();
+    if (reg.clientHeap == 0)
+        reg.clientHeap = reg.heap->createClientHeap();
+}
+
+void GPUHardware::Client::revokeAllHeaps() 
+{
+    if (smi.clientHeap != 0)
+        smi.clientHeap->revoke();
+    if (ebi.clientHeap != 0)
+        ebi.clientHeap->revoke();
+    if (reg.clientHeap != 0)
+        reg.clientHeap->revoke();
+}
+
+void GPUHardware::registerCallbackLocked(const sp<IGPUCallback>& callback,
+        Client& client)
+{
+    sp<IBinder> binder = callback->asBinder();
+    if (mRegisteredClients.add(binder, client.pid) >= 0) {
+        binder->linkToDeath(this);
+    }
+}
+
+void GPUHardware::binderDied(const wp<IBinder>& who)
+{
+    Mutex::Autolock _l(mLock);
+    pid_t pid = mRegisteredClients.valueFor(who);
+    if (pid != 0) {
+        ssize_t index = mClients.indexOfKey(pid);
+        if (index >= 0) {
+            //LOGD("*** removing client at %d", index);
+            Client& client(mClients.editValueAt(index));
+            client.revokeAllHeaps(); // not really needed in theory
+            mClients.removeItemsAt(index);
+            if (mClients.size() == 0) {
+                //LOGD("*** was last client closing everything");
+                mCallback.clear();
+                mAllocator.clear();
+                mCurrentAllocator.clear();
+                mSMIHeap.clear();
+                mREGHeap.clear();
+                
+                // NOTE: we cannot clear the EBI heap because surfaceflinger
+                // itself may be using it, since this is where surfaces
+                // are allocated. if we're in the middle of compositing 
+                // a surface (even if its process just died), we cannot
+                // rip the heap under our feet.
+                
+                mOwner = NO_OWNER;
+            }
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+sp<GPUHardwareInterface> GPUFactory::getGPU()
+{
+    return new GPUHardware();
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.h b/libs/surfaceflinger/GPUHardware/GPUHardware.h
new file mode 100644
index 0000000..3354528
--- /dev/null
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.h
@@ -0,0 +1,63 @@
+/*
+ * 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_GPU_HARDWARE_H
+#define ANDROID_GPU_HARDWARE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+
+#include <ui/ISurfaceComposer.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class IGPUCallback;
+
+class GPUHardwareInterface : public virtual RefBase
+{
+public:
+    virtual void                revoke(int pid) = 0;
+    virtual sp<MemoryDealer>    request(int pid) = 0;
+    virtual status_t            request(int pid, const sp<IGPUCallback>& callback,
+            ISurfaceComposer::gpu_info_t* gpu) = 0;
+
+    virtual status_t            friendlyRevoke() = 0;
+    
+    // used for debugging only...
+    virtual sp<SimpleBestFitAllocator> getAllocator() const  = 0;
+    virtual pid_t getOwner() const = 0;
+    virtual void unconditionalRevoke() = 0;
+};
+
+// ---------------------------------------------------------------------------
+
+class GPUFactory
+{    
+public:
+    // the gpu factory
+    static sp<GPUHardwareInterface> getGPU();
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GPU_HARDWARE_H
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
new file mode 100644
index 0000000..f65d669
--- /dev/null
+++ b/libs/surfaceflinger/Layer.cpp
@@ -0,0 +1,568 @@
+/*
+ * 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 <cutils/properties.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/StopWatch.h>
+
+#include <ui/PixelFormat.h>
+#include <ui/EGLDisplaySurface.h>
+
+#include "clz.h"
+#include "Layer.h"
+#include "LayerBitmap.h"
+#include "SurfaceFlinger.h"
+#include "VRamHeap.h"
+#include "DisplayHardware/DisplayHardware.h"
+
+
+#define DEBUG_RESIZE    0
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4;
+const char* const Layer::typeID = "Layer";
+
+// ---------------------------------------------------------------------------
+
+Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
+    :   LayerBaseClient(flinger, display, c, i),
+        mSecure(false),
+        mFrontBufferIndex(1),
+        mNeedsBlending(true),
+        mResizeTransactionDone(false),
+        mTextureName(-1U), mTextureWidth(0), mTextureHeight(0)
+{
+    // no OpenGL operation is possible here, since we might not be
+    // in the OpenGL thread.
+}
+
+Layer::~Layer()
+{
+    client->free(clientIndex());
+    // this should always be called from the OpenGL thread
+    if (mTextureName != -1U) {
+        //glDeleteTextures(1, &mTextureName);
+        deletedTextures.add(mTextureName);
+    }
+}
+
+void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
+{
+    LayerBase::initStates(w,h,flags);
+
+    if (flags & ISurfaceComposer::eDestroyBackbuffer)
+        lcblk->flags |= eNoCopyBack;
+}
+
+sp<LayerBaseClient::Surface> Layer::getSurface() const
+{
+    return mSurface;
+}
+
+status_t Layer::setBuffers( Client* client,
+                            uint32_t w, uint32_t h,
+                            PixelFormat format, uint32_t flags)
+{
+    PixelFormatInfo info;
+    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;
+
+    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::eGPU) {
+        // FIXME: this value should come from the h/w
+        alignment = 8; 
+        // 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;
+    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)
+            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);
+
+    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 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);
+        // the texture has not been created yet, this Layer has
+        // in fact never been drawn into. this happens frequently with
+        // SurfaceView.
+        clearWithOpenGL(clip);
+        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);
+    }
+}
+
+status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
+{
+    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()));
+
+    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?
+    }
+    return err;
+}
+
+uint32_t Layer::doTransaction(uint32_t flags)
+{
+    const Layer::State& front(drawingState());
+    const Layer::State& temp(currentState());
+
+    // the test front.{w|h} != temp.{w|h} is not enough because it is possible
+    // 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.
+
+    /*
+     *  Various states we could be in...
+
+         resize = state & eResizeRequested;
+         if (backbufferChanged) {
+             if (resize == 0) {
+                 // ERROR, the resized buffer doesn't have its resize flag set
+             } else if (resize == mask) {
+                 // ERROR one of the buffer has already been resized
+             } else if (resize == mask ^ eResizeRequested) {
+                 // ERROR, the resized buffer doesn't have its resize flag set
+             } else if (resize == eResizeRequested) {
+                 // OK, Normal case, proceed with resize
+             }
+         } else {
+             if (resize == 0) {
+                 // OK, nothing special, do nothing
+             } else if (resize == mask) {
+                 // restarted transaction, do nothing
+             } else if (resize == mask ^ eResizeRequested) {
+                 // restarted transaction, do nothing
+             } else if (resize == eResizeRequested) {
+                 // OK, size reset to previous value, proceed with resize
+             }
+         }
+     */
+
+    // Index of the back buffer
+    const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
+    const uint32_t state = lcblk->swapState;
+    const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
+    const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
+    uint32_t resizeFlags = state & eResizeRequested;
+
+    if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
+        LOGE(   "backbuffer size changed, but both resize flags are not set! "
+                "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
+                "index=%d, (%dx%d), (%dx%d)",
+                this,  state,
+                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()));
+        // 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
+        // client to get unblocked)
+        resizeFlags = eResizeRequested;
+    }
+
+    if (resizeFlags == eResizeRequested)  {
+        // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
+        // here, would be wrong and misleading because by this point
+        // mFrontBufferIndex has not been updated yet.
+
+        LOGD_IF(DEBUG_RESIZE,
+                    "resize (layer=%p), state=%08x, "
+                    "requested (%dx%d), "
+                    "drawing (%d,%d), "
+                    "index=%d, (%dx%d), (%dx%d)",
+                    this,  state,
+                    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()));
+
+        if (state & eLocked) {
+            // if the buffer is locked, we can't resize anything because
+            // - the backbuffer is currently in use by the user
+            // - the front buffer is being shown
+            // We just act as if the transaction didn't happen and we
+            // reschedule it later...
+            flags |= eRestartTransaction;
+        } else {
+            // This buffer needs to be resized
+            status_t err =
+                resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
+            if (err == NO_ERROR) {
+                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);
+                mResizeTransactionDone = true;
+
+                // we're being resized and there is a freeze display request,
+                // acquire a freeze lock, so that the screen stays put
+                // until we've redrawn at the new size; this is to avoid
+                // glitches upon orientation changes.
+                if (mFlinger->hasFreezeRequest()) {
+                    // if the surface is hidden, don't try to acquire the
+                    // freeze lock, since hidden surfaces may never redraw
+                    if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
+                        mFreezeLock = mFlinger->getFreezeLock();
+                    }
+                }
+            }
+        }
+    }
+    
+    if (temp.sequence != front.sequence) {
+        if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
+            // this surface is now hidden, so it shouldn't hold a freeze lock
+            // (it may never redraw, which is fine if it is hidden)
+            mFreezeLock.clear();
+        }
+    }
+        
+    return LayerBase::doTransaction(flags);
+}
+
+status_t Layer::resize(
+        int32_t clientBackBufferIndex,
+        uint32_t width, uint32_t height,
+        const char* what)
+{
+    /*
+     * handle resize (backbuffer and frontbuffer reallocation)
+     */
+
+    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);
+
+    LOGD_IF(!backbufferChanged,
+            "(%s) eResizeRequested (layer=%p), but size not changed: "
+            "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
+            "state=%08lx, index=%d, (%dx%d), (%dx%d)",
+            what, this,
+            int(width), int(height),
+            int(drawingState().w), int(drawingState().h),
+            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()));
+
+    // 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));
+    }
+    return err;
+}
+
+void Layer::setSizeChanged(uint32_t w, uint32_t h)
+{
+    LOGD_IF(DEBUG_RESIZE,
+            "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
+            w, h, mCurrentState.w, mCurrentState.h);
+    android_atomic_or(eResizeRequested, &(lcblk->swapState));
+}
+
+// ----------------------------------------------------------------------------
+// pageflip handling...
+// ----------------------------------------------------------------------------
+
+void Layer::lockPageFlip(bool& recomputeVisibleRegions)
+{
+    uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
+    // preemptively block the client, because he might set
+    // eFlipRequested at any time and want to use this buffer
+    // for the next frame. This will be unset below if it
+    // turns out we didn't need it.
+
+    uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
+    if (!(state & mask))
+        return;
+
+    if (UNLIKELY(state & eInvalidSurface)) {
+        // if eInvalidSurface is set, this means the surface
+        // became invalid during a transaction (NO_MEMORY for instance)
+        mFlinger->scheduleBroadcast(client);
+        return;
+    }
+
+    if (UNLIKELY(state & eFlipRequested)) {
+        uint32_t oldState;
+        mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
+        if (oldState & eNextFlipPending) {
+            // Process another round (we know at least a buffer
+            // is ready for that client).
+            mFlinger->signalEvent();
+        }
+    }
+}
+
+Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
+{
+    // atomically swap buffers and (re)set eFlipRequested
+    int32_t oldValue, newValue;
+    layer_cblk_t * const lcblk = this->lcblk;
+    do {
+        oldValue = lcblk->swapState;
+            // get the current value
+
+        LOG_ASSERT(oldValue&eFlipRequested,
+            "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
+            long(oldValue));
+
+        newValue = (oldValue ^ eIndex);
+            // swap buffers
+
+        newValue &= ~(eFlipRequested | eNextFlipPending);
+            // clear eFlipRequested and eNextFlipPending
+
+        if (oldValue & eNextFlipPending)
+            newValue |= eFlipRequested;
+            // if eNextFlipPending is set (second buffer already has something
+            // in it) we need to reset eFlipRequested because the client
+            // might never do it
+
+    } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
+    *previousSate = oldValue;
+
+    const int32_t index = (newValue & eIndex) ^ 1;
+    mFrontBufferIndex = index;
+
+    // ... post the new front-buffer
+    Region dirty(lcblk->region + index);
+    dirty.andSelf(frontBuffer().bounds());
+
+    //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
+    //    oldValue, newValue, mFrontBufferIndex);
+    //dirty.dump("dirty");
+
+    if (UNLIKELY(oldValue & eResizeRequested)) {
+
+        LOGD_IF(DEBUG_RESIZE,
+                     "post (layer=%p), state=%08x, "
+                     "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()));
+
+        // here, we just posted the surface and we have resolved
+        // the front/back buffer indices. The client is blocked, so
+        // it cannot start using the new backbuffer.
+
+        // If the backbuffer was resized in THIS round, we actually cannot
+        // resize the frontbuffer because it has *just* been drawn (and we
+        // would have nothing to draw). In this case we just skip the resize
+        // it'll happen after the next page flip or during the next
+        // transaction.
+
+        const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
+        if (mResizeTransactionDone && (newValue & mask)) {
+            // Resize the layer's second buffer only if the transaction
+            // happened. It may not have happened yet if eResizeRequested
+            // was set immediately after the "transactionRequested" test,
+            // in which case the drawing state's size would be wrong.
+            mFreezeLock.clear();
+            const Layer::State& s(drawingState());
+            if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
+                do {
+                    oldValue = lcblk->swapState;
+                    if ((oldValue & eResizeRequested) == eResizeRequested) {
+                        // ugh, another resize was requested since we processed
+                        // the first buffer, don't free the client, and let
+                        // the next transaction handle everything.
+                        break;
+                    }
+                    newValue = oldValue & ~mask;
+                } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
+            }
+            mResizeTransactionDone = false;
+            recomputeVisibleRegions = true;
+            this->contentDirty = true;
+        }
+    }
+
+    reloadTexture(dirty);
+
+    return dirty;
+}
+
+Point Layer::getPhysicalSize() const
+{
+    const LayerBitmap& front(frontBuffer());
+    return Point(front.width(), front.height());
+}
+
+void Layer::unlockPageFlip(
+        const Transform& planeTransform, Region& outDirtyRegion)
+{
+    Region dirtyRegion(mPostedDirtyRegion);
+    if (!dirtyRegion.isEmpty()) {
+        mPostedDirtyRegion.clear();
+        // The dirty region is given in the layer's coordinate space
+        // transform the dirty region by the surface's transformation
+        // and the global transformation.
+        const Layer::State& s(drawingState());
+        const Transform tr(planeTransform * s.transform);
+        dirtyRegion = tr.transform(dirtyRegion);
+
+        // At this point, the dirty region is in screen space.
+        // Make sure it's constrained by the visible region (which
+        // is in screen space as well).
+        dirtyRegion.andSelf(visibleRegionScreen);
+        outDirtyRegion.orSelf(dirtyRegion);
+
+        // client could be blocked, so signal them so they get a
+        // chance to reevaluate their condition.
+        mFlinger->scheduleBroadcast(client);
+    }
+}
+
+void Layer::finishPageFlip()
+{
+    if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
+        LOGE_IF(!(lcblk->swapState & eBusy),
+                "layer %p wasn't locked!", this);
+        android_atomic_and(~eBusy, &(lcblk->swapState));
+    }
+    mFlinger->scheduleBroadcast(client);
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+}; // namespace android
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
new file mode 100644
index 0000000..2867f2b
--- /dev/null
+++ b/libs/surfaceflinger/Layer.h
@@ -0,0 +1,120 @@
+/*
+ * 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_LAYER_H
+#define ANDROID_LAYER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <ui/PixelFormat.h>
+
+#include <private/ui/SharedState.h>
+#include <private/ui/LayerState.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+#include "LayerBitmap.h"
+#include "LayerBase.h"
+#include "Transform.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class Client;
+class LayerBitmap;
+class MemoryDealer;
+class FreezeLock;
+
+// ---------------------------------------------------------------------------
+
+class Layer : public LayerBaseClient
+{
+public:    
+    static const uint32_t typeInfo;
+    static const char* const typeID;
+    virtual char const* getTypeID() const { return typeID; }
+    virtual uint32_t getTypeInfo() const { return typeInfo; }
+
+                 Layer(SurfaceFlinger* flinger, DisplayID display,
+                         Client* c, int32_t i);
+
+        virtual ~Layer();
+
+    inline PixelFormat pixelFormat() const {
+        return frontBuffer().pixelFormat();
+    }
+
+    status_t setBuffers(    Client* client,
+                            uint32_t w, uint32_t h,
+                            PixelFormat format, uint32_t flags=0);
+
+    virtual void onDraw(const Region& clip) const;
+    virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
+    virtual void setSizeChanged(uint32_t w, uint32_t h);
+    virtual uint32_t doTransaction(uint32_t transactionFlags);
+    virtual Point getPhysicalSize() const;
+    virtual void lockPageFlip(bool& recomputeVisibleRegions);
+    virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
+    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;
+
+    const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; }
+          LayerBitmap& getBuffer(int i)       { return mBuffers[i]; }
+
+    // only for debugging
+    const sp<FreezeLock>&  getFreezeLock() const { return mFreezeLock; }
+
+private:
+    inline const LayerBitmap&
+            frontBuffer() const { return getBuffer(mFrontBufferIndex); }
+    inline LayerBitmap&
+            frontBuffer()       { return getBuffer(mFrontBufferIndex); }
+    inline const LayerBitmap&
+            backBuffer() const  { return getBuffer(1-mFrontBufferIndex); }
+    inline LayerBitmap&
+            backBuffer()        { return getBuffer(1-mFrontBufferIndex); }
+
+    void reloadTexture(const Region& dirty);
+
+    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<Surface>             mSurface;
+
+            bool            mSecure;
+            LayerBitmap     mBuffers[2];
+            int32_t         mFrontBufferIndex;
+            bool            mNeedsBlending;
+            bool            mResizeTransactionDone;
+            Region          mPostedDirtyRegion;
+            sp<FreezeLock>  mFreezeLock;
+            
+            GLuint          mTextureName;
+            GLuint          mTextureWidth;
+            GLuint          mTextureHeight;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_H
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
new file mode 100644
index 0000000..0cf53f7
--- /dev/null
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -0,0 +1,740 @@
+/*
+ * 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 <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <hardware/hardware.h>
+
+#include "clz.h"
+#include "LayerBase.h"
+#include "LayerBlur.h"
+#include "SurfaceFlinger.h"
+#include "DisplayHardware/DisplayHardware.h"
+
+
+// We don't honor the premultiplied alpha flags, which means that
+// premultiplied surface may be composed using a non-premultiplied
+// equation. We do this because it may be a lot faster on some hardware
+// The correct value is HONOR_PREMULTIPLIED_ALPHA = 1
+#define HONOR_PREMULTIPLIED_ALPHA   0
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+const uint32_t LayerBase::typeInfo = 1;
+const char* const LayerBase::typeID = "LayerBase";
+
+const uint32_t LayerBaseClient::typeInfo = LayerBase::typeInfo | 2;
+const char* const LayerBaseClient::typeID = "LayerBaseClient";
+
+// ---------------------------------------------------------------------------
+
+Vector<GLuint> LayerBase::deletedTextures; 
+
+int32_t LayerBase::sIdentity = 0;
+
+LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
+    : dpy(display), contentDirty(false),
+      mFlinger(flinger),
+      mTransformed(false),
+      mOrientation(0),
+      mCanUseCopyBit(false),
+      mTransactionFlags(0),
+      mPremultipliedAlpha(true),
+      mIdentity(uint32_t(android_atomic_inc(&sIdentity))),
+      mInvalidate(0)
+{
+    const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
+    mFlags = hw.getFlags();
+}
+
+LayerBase::~LayerBase()
+{
+}
+
+const GraphicPlane& LayerBase::graphicPlane(int dpy) const
+{ 
+    return mFlinger->graphicPlane(dpy);
+}
+
+GraphicPlane& LayerBase::graphicPlane(int dpy)
+{
+    return mFlinger->graphicPlane(dpy); 
+}
+
+void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
+{
+    uint32_t layerFlags = 0;
+    if (flags & ISurfaceComposer::eHidden)
+        layerFlags = ISurfaceComposer::eLayerHidden;
+
+    if (flags & ISurfaceComposer::eNonPremultiplied)
+        mPremultipliedAlpha = false;
+
+    mCurrentState.z         = 0;
+    mCurrentState.w         = w;
+    mCurrentState.h         = h;
+    mCurrentState.alpha     = 0xFF;
+    mCurrentState.flags     = layerFlags;
+    mCurrentState.sequence  = 0;
+    mCurrentState.transform.set(0, 0);
+
+    // drawing state & current state are identical
+    mDrawingState = mCurrentState;
+}
+
+void LayerBase::commitTransaction(bool skipSize) {
+    const uint32_t w = mDrawingState.w;
+    const uint32_t h = mDrawingState.h;
+    mDrawingState = mCurrentState;
+    if (skipSize) {
+        mDrawingState.w = w;
+        mDrawingState.h = h;
+    }
+}
+void LayerBase::forceVisibilityTransaction() {
+    // this can be called without SurfaceFlinger.mStateLock, but if we
+    // can atomically increment the sequence number, it doesn't matter.
+    android_atomic_inc(&mCurrentState.sequence);
+    requestTransaction();
+}
+bool LayerBase::requestTransaction() {
+    int32_t old = setTransactionFlags(eTransactionNeeded);
+    return ((old & eTransactionNeeded) == 0);
+}
+uint32_t LayerBase::getTransactionFlags(uint32_t flags) {
+    return android_atomic_and(~flags, &mTransactionFlags) & flags;
+}
+uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
+    return android_atomic_or(flags, &mTransactionFlags);
+}
+
+void LayerBase::setSizeChanged(uint32_t w, uint32_t h) {
+}
+
+bool LayerBase::setPosition(int32_t x, int32_t y) {
+    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.transform.set(x, y);
+    requestTransaction();
+    return true;
+}
+bool LayerBase::setLayer(uint32_t z) {
+    if (mCurrentState.z == z)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.z = z;
+    requestTransaction();
+    return true;
+}
+bool LayerBase::setSize(uint32_t w, uint32_t h) {
+    if (mCurrentState.w == w && mCurrentState.h == h)
+        return false;
+    setSizeChanged(w, h);
+    mCurrentState.w = w;
+    mCurrentState.h = h;
+    requestTransaction();
+    return true;
+}
+bool LayerBase::setAlpha(uint8_t alpha) {
+    if (mCurrentState.alpha == alpha)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.alpha = alpha;
+    requestTransaction();
+    return true;
+}
+bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) {
+    // TODO: check the matrix has changed
+    mCurrentState.sequence++;
+    mCurrentState.transform.set(
+            matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
+    requestTransaction();
+    return true;
+}
+bool LayerBase::setTransparentRegionHint(const Region& transparent) {
+    // TODO: check the region has changed
+    mCurrentState.sequence++;
+    mCurrentState.transparentRegion = transparent;
+    requestTransaction();
+    return true;
+}
+bool LayerBase::setFlags(uint8_t flags, uint8_t mask) {
+    const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
+    if (mCurrentState.flags == newFlags)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.flags = newFlags;
+    requestTransaction();
+    return true;
+}
+
+Rect LayerBase::visibleBounds() const
+{
+    return mTransformedBounds;
+}      
+
+void LayerBase::setVisibleRegion(const Region& visibleRegion) {
+    // always called from main thread
+    visibleRegionScreen = visibleRegion;
+}
+
+void LayerBase::setCoveredRegion(const Region& coveredRegion) {
+    // always called from main thread
+    coveredRegionScreen = coveredRegion;
+}
+
+uint32_t LayerBase::doTransaction(uint32_t flags)
+{
+    const Layer::State& front(drawingState());
+    const Layer::State& temp(currentState());
+
+    if (temp.sequence != front.sequence) {
+        // invalidate and recompute the visible regions if needed
+        flags |= eVisibleRegion;
+        this->contentDirty = true;
+    }
+    
+    // Commit the transaction
+    commitTransaction(flags & eRestartTransaction);
+    return flags;
+}
+
+Point LayerBase::getPhysicalSize() const
+{
+    const Layer::State& front(drawingState());
+    return Point(front.w, front.h);
+}
+
+void LayerBase::validateVisibility(const Transform& planeTransform)
+{
+    const Layer::State& s(drawingState());
+    const Transform tr(planeTransform * s.transform);
+    const bool transformed = tr.transformed();
+   
+    const Point size(getPhysicalSize());
+    uint32_t w = size.x;
+    uint32_t h = size.y;    
+    tr.transform(mVertices[0], 0, 0);
+    tr.transform(mVertices[1], 0, h);
+    tr.transform(mVertices[2], w, h);
+    tr.transform(mVertices[3], w, 0);
+    if (UNLIKELY(transformed)) {
+        // NOTE: here we could also punt if we have too many rectangles
+        // in the transparent region
+        if (tr.preserveRects()) {
+            // transform the transparent region
+            transparentRegionScreen = tr.transform(s.transparentRegion);
+        } else {
+            // transformation too complex, can't do the transparent region
+            // optimization.
+            transparentRegionScreen.clear();
+        }
+    } else {
+        transparentRegionScreen = s.transparentRegion;
+    }
+
+    // cache a few things...
+    mOrientation = tr.getOrientation();
+    mTransformedBounds = tr.makeBounds(w, h);
+    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)
+{
+}
+
+void LayerBase::unlockPageFlip(
+        const Transform& planeTransform, Region& outDirtyRegion)
+{
+    if ((android_atomic_and(~1, &mInvalidate)&1) == 1) {
+        outDirtyRegion.orSelf(visibleRegionScreen);
+    }
+}
+
+void LayerBase::finishPageFlip()
+{
+}
+
+void LayerBase::invalidate()
+{
+    if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
+        mFlinger->signalEvent();
+    }
+}
+
+void LayerBase::drawRegion(const Region& reg) const
+{
+    Region::iterator iterator(reg);
+    if (iterator) {
+        Rect r;
+        const DisplayHardware& hw(graphicPlane(0).displayHardware());
+        const int32_t fbWidth  = hw.getWidth();
+        const int32_t fbHeight = hw.getHeight();
+        const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, 
+                { fbWidth, fbHeight }, { 0, fbHeight }  };
+        glVertexPointer(2, GL_SHORT, 0, vertices);
+        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); 
+        }
+    }
+}
+
+void LayerBase::draw(const Region& inClip) const
+{
+    // invalidate the region we'll update
+    Region clip(inClip);  // copy-on-write, so no-op most of the time
+
+    // Remove the transparent area from the clipping region
+    const State& s = drawingState();
+    if (LIKELY(!s.transparentRegion.isEmpty())) {
+        clip.subtract(transparentRegionScreen);
+        if (clip.isEmpty()) {
+            // usually this won't happen because this should be taken care of
+            // by SurfaceFlinger::computeVisibleRegions()
+            return;
+        }        
+    }
+
+    // reset GL state
+    glEnable(GL_SCISSOR_TEST);
+
+    onDraw(clip);
+
+    /*
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_DITHER);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+    glColor4x(0, 0x8000, 0, 0x10000);
+    drawRegion(transparentRegionScreen);
+    glDisable(GL_BLEND);
+    */
+}
+
+GLuint LayerBase::createTexture() const
+{
+    GLuint textureName = -1;
+    glGenTextures(1, &textureName);
+    glBindTexture(GL_TEXTURE_2D, textureName);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    if (mFlags & DisplayHardware::SLOW_CONFIG) {
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    } else {
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    }
+    return textureName;
+}
+
+void LayerBase::clearWithOpenGL(const Region& clip) const
+{
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t fbHeight = hw.getHeight();
+    glColor4x(0,0,0,0);
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_BLEND);
+    glDisable(GL_DITHER);
+    Rect r;
+    Region::iterator iterator(clip);
+    if (iterator) {
+        glEnable(GL_SCISSOR_TEST);
+        glVertexPointer(2, GL_FIXED, 0, mVertices);
+        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); 
+        }
+    }
+}
+
+void LayerBase::drawWithOpenGL(const Region& clip,
+        GLint textureName, const GGLSurface& t, int transform) const
+{
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t fbHeight = hw.getHeight();
+    const State& s(drawingState());
+
+    // bind our texture
+    validateTexture(textureName);
+    glEnable(GL_TEXTURE_2D);
+
+    // Dithering...
+    if (s.flags & ISurfaceComposer::eLayerDither) {
+        glEnable(GL_DITHER);
+    } else {
+        glDisable(GL_DITHER);
+    }
+
+    if (UNLIKELY(s.alpha < 0xFF)) {
+        // We have an alpha-modulation. We need to modulate all
+        // texture components by alpha because we're always using 
+        // premultiplied alpha.
+        
+        // If the texture doesn't have an alpha channel we can
+        // use REPLACE and switch to non premultiplied alpha
+        // blending (SRCA/ONE_MINUS_SRCA).
+        
+        GLenum env, src;
+        if (needsBlending()) {
+            env = GL_MODULATE;
+            src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
+        } else {
+            env = GL_REPLACE;
+            src = GL_SRC_ALPHA;
+        }
+        const GGLfixed alpha = (s.alpha << 16)/255;
+        glColor4x(alpha, alpha, alpha, alpha);
+        glEnable(GL_BLEND);
+        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
+    } else {
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
+        if (needsBlending()) {
+            GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
+            glEnable(GL_BLEND);
+            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
+        } else {
+            glDisable(GL_BLEND);
+        }
+    }
+
+    if (UNLIKELY(transformed()
+            || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) 
+    {
+        //StopWatch watch("GL transformed");
+        Region::iterator iterator(clip);
+        if (iterator) {
+            // always use high-quality filtering with fast configurations
+            bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG);
+            if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
+                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            }            
+            const GLfixed texCoords[4][2] = {
+                    { 0,        0 },
+                    { 0,        0x10000 },
+                    { 0x10000,  0x10000 },
+                    { 0x10000,  0 }
+            };
+
+            glMatrixMode(GL_TEXTURE);
+            glLoadIdentity();
+            
+            if (transform == HAL_TRANSFORM_ROT_90) {
+                glTranslatef(0, 1, 0);
+                glRotatef(-90, 0, 0, 1);
+            }
+
+            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;
+                // 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;
+                glScalef(ws, hs, 1.0f);
+            }
+
+            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            glVertexPointer(2, GL_FIXED, 0, mVertices);
+            glTexCoordPointer(2, GL_FIXED, 0, texCoords);
+
+            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); 
+            }
+
+            if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
+                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            }
+            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+        }
+    } else {
+        Region::iterator iterator(clip);
+        if (iterator) {
+            Rect r;
+            GLint crop[4] = { 0, t.height, t.width, -t.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)) {
+                const GLint sy = fbHeight - (r.top + r.height());
+                glScissor(r.left, sy, r.width(), r.height());
+                glDrawTexiOES(x, y, 0, t.width, t.height);
+            }
+        }
+    }
+}
+
+void LayerBase::validateTexture(GLint textureName) const
+{
+    glBindTexture(GL_TEXTURE_2D, textureName);
+    // TODO: reload the texture if needed
+    // this is currently done in loadTexture() below
+}
+
+void LayerBase::loadTexture(const Region& dirty,
+        GLint textureName, const GGLSurface& t,
+        GLuint& textureWidth, GLuint& textureHeight) const
+{
+    // TODO: defer the actual texture reload until LayerBase::validateTexture
+    // is called.
+
+    uint32_t flags = mFlags;
+    glBindTexture(GL_TEXTURE_2D, textureName);
+
+    GLuint tw = t.width;
+    GLuint th = t.height;
+
+    /*
+     * 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).
+     * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
+     * need to do something reasonable (here creating a bigger texture).
+     * 
+     * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT);
+     * 
+     * This situation doesn't happen often, but some h/w have a limitation
+     * for their framebuffer (eg: must be multiple of 8 pixels), and
+     * we need to take that into account when using these buffers as
+     * textures.
+     *
+     * This should never be a problem with POT textures
+     */
+
+    tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4);
+
+    /*
+     * round to POT if needed 
+     */
+    
+    GLuint texture_w = tw;
+    GLuint texture_h = th;
+    if (!(flags & DisplayHardware::NPOT_EXTENSION)) {
+        // find the smallest power-of-two that will accommodate our surface
+        texture_w = 1 << (31 - clz(t.width));
+        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
+
+            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
+                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;
+            }
+            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);
+            }
+        }
+    }
+}
+
+bool LayerBase::canUseCopybit() const
+{
+    return mCanUseCopyBit;
+}
+
+// ---------------------------------------------------------------------------
+
+LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
+        Client* c, int32_t i)
+    : LayerBase(flinger, display), client(c),
+      lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ),
+      mIndex(i)
+{
+    if (client) {
+        client->bindLayer(this, i);
+
+        // Initialize this layer's control block
+        memset(this->lcblk, 0, sizeof(layer_cblk_t));
+        this->lcblk->identity = mIdentity;
+        Region::writeEmpty(&(this->lcblk->region[0]), sizeof(flat_region_t));
+        Region::writeEmpty(&(this->lcblk->region[1]), sizeof(flat_region_t));
+    }
+}
+
+LayerBaseClient::~LayerBaseClient()
+{
+    if (client) {
+        client->free(mIndex);
+    }
+}
+
+int32_t LayerBaseClient::serverIndex() const {
+    if (client) {
+        return (client->cid<<16)|mIndex;
+    }
+    return 0xFFFF0000 | mIndex;
+}
+
+sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const
+{
+    return new Surface(clientIndex(), mIdentity);
+}
+
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
new file mode 100644
index 0000000..a020f44
--- /dev/null
+++ b/libs/surfaceflinger/LayerBase.h
@@ -0,0 +1,356 @@
+/*
+ * 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_LAYER_BASE_H
+#define ANDROID_LAYER_BASE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <private/ui/LayerState.h>
+
+#include <ui/Region.h>
+#include <ui/Overlay.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+#include "Transform.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class SurfaceFlinger;
+class DisplayHardware;
+class GraphicPlane;
+class Client;
+
+// ---------------------------------------------------------------------------
+
+class LayerBase
+{
+    // poor man's dynamic_cast below
+    template<typename T>
+    struct getTypeInfoOfAnyType {
+        static uint32_t get() { return T::typeInfo; }
+    };
+
+    template<typename T>
+    struct getTypeInfoOfAnyType<T*> {
+        static uint32_t get() { return getTypeInfoOfAnyType<T>::get(); }
+    };
+
+public:
+    static const uint32_t typeInfo;
+    static const char* const typeID;
+    virtual char const* getTypeID() const { return typeID; }
+    virtual uint32_t getTypeInfo() const { return typeInfo; }
+    
+    template<typename T>
+    static T dynamicCast(LayerBase* base) {
+        uint32_t mostDerivedInfo = base->getTypeInfo();
+        uint32_t castToInfo = getTypeInfoOfAnyType<T>::get();
+        if ((mostDerivedInfo & castToInfo) == castToInfo)
+            return static_cast<T>(base);
+        return 0;
+    }
+
+    
+    static Vector<GLuint> deletedTextures; 
+
+    LayerBase(SurfaceFlinger* flinger, DisplayID display);
+    virtual ~LayerBase();
+    
+    DisplayID           dpy;
+    mutable bool        contentDirty;
+            Region      visibleRegionScreen;
+            Region      transparentRegionScreen;
+            Region      coveredRegionScreen;
+            
+            struct State {
+                uint32_t        w;
+                uint32_t        h;
+                uint32_t        z;
+                uint8_t         alpha;
+                uint8_t         flags;
+                uint8_t         reserved[2];
+                int32_t         sequence;   // changes when visible regions can change
+                uint32_t        tint;
+                Transform       transform;
+                Region          transparentRegion;
+            };
+
+            // modify current state
+            bool setPosition(int32_t x, int32_t y);
+            bool setLayer(uint32_t z);
+            bool setSize(uint32_t w, uint32_t h);
+            bool setAlpha(uint8_t alpha);
+            bool setMatrix(const layer_state_t::matrix22_t& matrix);
+            bool setTransparentRegionHint(const Region& opaque);
+            bool setFlags(uint8_t flags, uint8_t mask);
+            
+            void commitTransaction(bool skipSize);
+            bool requestTransaction();
+            void forceVisibilityTransaction();
+            
+            uint32_t getTransactionFlags(uint32_t flags);
+            uint32_t setTransactionFlags(uint32_t flags);
+            
+            Rect visibleBounds() const;
+            void drawRegion(const Region& reg) const;
+
+            void invalidate();
+            
+    /**
+     * draw - performs some global clipping optimizations
+     * and calls onDraw().
+     * Typically this method is not overridden, instead implement onDraw()
+     * to perform the actual drawing.  
+     */
+    virtual void draw(const Region& clip) const;
+    
+    /**
+     * onDraw - draws the surface.
+     */
+    virtual void onDraw(const Region& clip) const = 0;
+    
+    /**
+     * initStates - called just after construction
+     */
+    virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
+    
+    /**
+     * setSizeChanged - called when the *current* state's size is changed.
+     */
+    virtual void setSizeChanged(uint32_t w, uint32_t h);
+    
+    /**
+     * doTransaction - process the transaction. This is a good place to figure
+     * out which attributes of the surface have changed.
+     */
+    virtual uint32_t doTransaction(uint32_t transactionFlags);
+    
+    /**
+     * setVisibleRegion - called to set the new visible region. This gives
+     * a chance to update the new visible region or record the fact it changed.
+     */
+    virtual void setVisibleRegion(const Region& visibleRegion);
+    
+    /**
+     * setCoveredRegion - called when the covered region changes. The covered
+     * region correspond to any area of the surface that is covered 
+     * (transparently or not) by another surface.
+     */
+    virtual void setCoveredRegion(const Region& coveredRegion);
+    
+    /**
+     * getPhysicalSize - returns the physical size of the drawing state of
+     * the surface. If the surface is backed by a bitmap, this is the size of
+     * the bitmap (as opposed to the size of the drawing state).
+     */
+    virtual Point getPhysicalSize() const;
+
+    /**
+     * validateVisibility - cache a bunch of things
+     */
+    virtual void validateVisibility(const Transform& globalTransform);
+
+    /**
+     * lockPageFlip - called each time the screen is redrawn and returns whether
+     * the visible regions need to be recomputed (this is a fairly heavy
+     * operation, so this should be set only if needed). Typically this is used
+     * to figure out if the content or size of a surface has changed.
+     */
+    virtual void lockPageFlip(bool& recomputeVisibleRegions);
+    
+    /**
+     * unlockPageFlip - called each time the screen is redrawn. updates the
+     * final dirty region wrt the planeTransform.
+     * At this point, all visible regions, surface position and size, etc... are
+     * correct.
+     */
+    virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
+    
+    /**
+     * finishPageFlip - called after all surfaces have drawn.
+     */
+    virtual void finishPageFlip();
+    
+    /**
+     * needsBlending - true if this surface needs blending
+     */
+    virtual bool needsBlending() const  { return false; }
+
+    /**
+     * transformed -- true is this surface needs a to be transformed
+     */
+    virtual bool transformed() const    { return mTransformed; }
+
+    /**
+     * isSecure - true if this surface is secure, that is if it prevents
+     * screenshots or vns servers.
+     */
+    virtual bool isSecure() const       { return false; }
+
+            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) {
+        return layerA[0]->currentState().z - layerB[0]->currentState().z;
+    }
+
+    int32_t  getOrientation() const { return mOrientation; }
+    int  tx() const             { return mLeft; }
+    int  ty() const             { return mTop; }
+    
+protected:
+    const GraphicPlane& graphicPlane(int dpy) const;
+          GraphicPlane& graphicPlane(int dpy);
+
+          GLuint createTexture() const;
+    
+          void drawWithOpenGL(const Region& clip,
+                  GLint textureName,
+                  const GGLSurface& surface,
+                  int transform = 0) const;
+
+          void clearWithOpenGL(const Region& clip) const;
+
+          void loadTexture(const Region& dirty,
+                  GLint textureName, const GGLSurface& t,
+                  GLuint& textureWidth, GLuint& textureHeight) const;
+
+          bool canUseCopybit() const;
+          
+                SurfaceFlinger* mFlinger;
+                uint32_t        mFlags;
+
+                // cached during validateVisibility()
+                bool            mTransformed;
+                int32_t         mOrientation;
+                GLfixed         mVertices[4][2];
+                Rect            mTransformedBounds;
+                bool            mCanUseCopyBit;
+                int             mLeft;
+                int             mTop;
+            
+                // these are protected by an external lock
+                State           mCurrentState;
+                State           mDrawingState;
+    volatile    int32_t         mTransactionFlags;
+
+                // don't change, don't need a lock
+                bool            mPremultipliedAlpha;
+
+                // only read
+    const       uint32_t        mIdentity;
+     
+                // atomic
+    volatile    int32_t         mInvalidate;
+                
+
+private:
+                void validateTexture(GLint textureName) const;
+    static      int32_t         sIdentity;
+};
+
+
+// ---------------------------------------------------------------------------
+
+class LayerBaseClient : public LayerBase
+{
+public:
+    class Surface;
+   static const uint32_t typeInfo;
+    static const char* const typeID;
+    virtual char const* getTypeID() const { return typeID; }
+    virtual uint32_t getTypeInfo() const { return typeInfo; }
+
+    LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, 
+            Client* client, int32_t i);
+    virtual ~LayerBaseClient();
+
+
+    Client*             const client;
+    layer_cblk_t*       const lcblk;
+
+    inline  int32_t     clientIndex() const { return mIndex; }
+            int32_t     serverIndex() const;
+
+    virtual sp<Surface> getSurface() const;
+   
+            uint32_t    getIdentity() const { return mIdentity; }
+
+    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;
+        }
+
+        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;
+        };
+
+    private:
+        ISurfaceFlingerClient::surface_data_t mParams;
+    };
+
+private:
+    int32_t mIndex;
+
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_BASE_H
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
new file mode 100644
index 0000000..e844350
--- /dev/null
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -0,0 +1,185 @@
+/*
+ * 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 <cutils/memory.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/MemoryDealer.h>
+#include <utils/IMemory.h>
+#include <ui/PixelFormat.h>
+#include <pixelflinger/pixelflinger.h>
+
+#include "LayerBitmap.h"
+#include "SurfaceFlinger.h"
+#include "VRamHeap.h"
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+LayerBitmap::LayerBitmap()
+    : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2)
+{
+    memset(&mSurface, 0, sizeof(mSurface));
+}
+
+LayerBitmap::~LayerBitmap()
+{
+    mSurface.data = 0;
+}
+
+status_t LayerBitmap::init(const sp<MemoryDealer>& allocator)
+{
+    if (mAllocator != NULL)
+        return BAD_VALUE;
+    mAllocator = allocator;
+    return NO_ERROR;
+}
+
+status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, 
+        PixelFormat format, uint32_t flags)
+{
+    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", size);
+        allocator->dump("LayerBitmap");
+        mSurface.data = 0;
+        mSize = -1U;
+        return NO_MEMORY;
+    }
+    return NO_ERROR;
+}
+
+void LayerBitmap::clear()
+{
+    // 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);
+        //}
+    }
+}
+
+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();
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
new file mode 100644
index 0000000..9ad64c4
--- /dev/null
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -0,0 +1,84 @@
+/*
+ * 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_LAYER_BITMAP_H
+#define ANDROID_LAYER_BITMAP_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Atomic.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <private/ui/SharedState.h>
+#include <pixelflinger/pixelflinger.h>
+
+class copybit_image_t;
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class IMemory;
+class MemoryDealer;
+class LayerBitmap;
+
+// ---------------------------------------------------------------------------
+
+class LayerBitmap
+{
+public:
+
+    enum {
+        // erase memory to ensure security when necessary
+        SECURE_BITS = 0x00000001
+    };
+
+                LayerBitmap();
+                ~LayerBitmap();
+    status_t    init(const sp<MemoryDealer>& allocator);
+
+    status_t    setBits(uint32_t w, uint32_t h, uint32_t alignment,
+                        PixelFormat format, uint32_t flags = 0);
+    void        clear();
+
+    status_t    getInfo(surface_info_t* info) const;
+    status_t    resize(uint32_t w, uint32_t h);
+
+    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;
+
+private:
+    sp<MemoryDealer>        mAllocator;
+    sp<IMemory>             mBitsMemory;
+    uint32_t                mAllocFlags;
+    ssize_t                 mOffset;
+    GGLSurface              mSurface;
+    size_t                  mSize;
+    uint32_t                mAlignment;
+};
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_BITMAP_H
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
new file mode 100644
index 0000000..d3e456f
--- /dev/null
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -0,0 +1,234 @@
+/*
+ * 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 <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include "BlurFilter.h"
+#include "LayerBlur.h"
+#include "SurfaceFlinger.h"
+#include "DisplayHardware/DisplayHardware.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+const uint32_t LayerBlur::typeInfo = LayerBaseClient::typeInfo | 8;
+const char* const LayerBlur::typeID = "LayerBlur";
+
+// ---------------------------------------------------------------------------
+
+LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
+        Client* client, int32_t i)
+     : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
+     mRefreshCache(true), mCacheAge(0), mTextureName(-1U)
+{
+}
+
+LayerBlur::~LayerBlur()
+{
+    if (mTextureName != -1U) {
+        //glDeleteTextures(1, &mTextureName);
+        deletedTextures.add(mTextureName);
+    }
+}
+
+void LayerBlur::setVisibleRegion(const Region& visibleRegion)
+{
+    LayerBaseClient::setVisibleRegion(visibleRegion);
+    if (visibleRegionScreen.isEmpty()) {
+        if (mTextureName != -1U) {
+            // We're not visible, free the texture up.
+            glBindTexture(GL_TEXTURE_2D, 0);
+            glDeleteTextures(1, &mTextureName);
+            mTextureName = -1U;
+        }
+    }
+}
+
+uint32_t LayerBlur::doTransaction(uint32_t flags)
+{
+    // we're doing a transaction, refresh the cache!
+    if (!mFlinger->isFrozen()) {
+        mRefreshCache = true;
+        mCacheDirty = true;
+        flags |= eVisibleRegion;
+        this->contentDirty = true;
+    }
+    return LayerBase::doTransaction(flags);    
+}
+
+void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion)
+{
+    // this code-path must be as tight as possible, it's called each time
+    // the screen is composited.
+    if (UNLIKELY(!visibleRegionScreen.isEmpty())) {
+        // if anything visible below us is invalidated, the cache becomes dirty
+        if (!mCacheDirty && 
+                !visibleRegionScreen.intersect(outDirtyRegion).isEmpty()) {
+            mCacheDirty = true;
+        }
+        if (mCacheDirty) {
+            if (!mFlinger->isFrozen()) {
+                // update everything below us that is visible
+                outDirtyRegion.orSelf(visibleRegionScreen);
+                nsecs_t now = systemTime();
+                if ((now - mCacheAge) >= ms2ns(500)) {
+                    mCacheAge = now;
+                    mRefreshCache = true;
+                    mCacheDirty = false;
+                } else {
+                    if (!mAutoRefreshPending) {
+                        mFlinger->signalDelayedEvent(ms2ns(500));
+                        mAutoRefreshPending = true;
+                    }
+                }
+            }
+        }
+    }
+    LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);
+}
+
+void LayerBlur::onDraw(const Region& clip) const
+{
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t fbHeight = hw.getHeight();
+    int x = mTransformedBounds.left;
+    int y = mTransformedBounds.top;
+    int w = mTransformedBounds.width();
+    int h = mTransformedBounds.height();
+    GLint X = x;
+    GLint Y = fbHeight - (y + h);
+    if (X < 0) {
+        w += X;
+        X = 0;
+    }
+    if (Y < 0) {
+        h += Y;
+        Y = 0;
+    }
+    if (w<0 || h<0) {
+        // we're outside of the framebuffer
+        return;
+    }
+
+    if (mTextureName == -1U) {
+        // create the texture name the first time
+        // can't do that in the ctor, because it runs in another thread.
+        glGenTextures(1, &mTextureName);
+    }
+
+    Region::iterator iterator(clip);
+    if (iterator) {
+        glEnable(GL_TEXTURE_2D);
+        glBindTexture(GL_TEXTURE_2D, mTextureName);
+    
+        if (mRefreshCache) {
+            mRefreshCache = false;
+            mAutoRefreshPending = false;
+            
+            // allocate enough memory for 4-bytes (2 pixels) aligned data
+            const int32_t s = (w + 1) & ~1;
+            uint16_t* const pixels = (uint16_t*)malloc(s*h*2);
+
+            // This reads the frame-buffer, so a h/w GL would have to
+            // finish() its rendering first. we don't want to do that
+            // too often. Read data is 4-bytes aligned.
+            glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+            
+            // blur that texture.
+            GGLSurface bl;
+            bl.version = sizeof(GGLSurface);
+            bl.width = w;
+            bl.height = h;
+            bl.stride = s;
+            bl.format = GGL_PIXEL_FORMAT_RGB_565;
+            bl.data = (GGLubyte*)pixels;            
+            blurFilter(&bl, 8, 2);
+            
+            // NOTE: this works only because we have POT. we'd have to round the
+            // texture size up, otherwise.
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
+                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+
+            free((void*)pixels);
+        }
+        
+        const State& s = drawingState();
+        if (UNLIKELY(s.alpha < 0xFF)) {
+            const GGLfixed alpha = (s.alpha << 16)/255;
+            glColor4x(0, 0, 0, alpha);
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        } else {
+            glDisable(GL_BLEND);
+        }
+
+        glDisable(GL_DITHER);
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+        if (UNLIKELY(transformed()
+                || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) {
+            // This is a very rare scenario.
+            glMatrixMode(GL_TEXTURE);
+            glLoadIdentity();
+            glScalef(1.0f/w, -1.0f/h, 1);
+            glTranslatef(-x, -y, 0);
+            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            glVertexPointer(2, GL_FIXED, 0, mVertices);
+            glTexCoordPointer(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); 
+            }       
+        } 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);
+                }
+            }
+        }
+    }
+
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
new file mode 100644
index 0000000..24b1156
--- /dev/null
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -0,0 +1,65 @@
+/*
+ * 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_LAYER_BLUR_H
+#define ANDROID_LAYER_BLUR_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <private/ui/LayerState.h>
+
+#include <ui/Region.h>
+
+#include "LayerBase.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class LayerBlur : public LayerBaseClient
+{
+public:    
+    static const uint32_t typeInfo;
+    static const char* const typeID;
+    virtual char const* getTypeID() const { return typeID; }
+    virtual uint32_t getTypeInfo() const { return typeInfo; }
+    
+                LayerBlur(SurfaceFlinger* flinger, DisplayID display,
+                        Client* client, int32_t i);
+        virtual ~LayerBlur();
+
+    virtual void onDraw(const Region& clip) const;
+    virtual bool needsBlending() const  { return true; }
+    virtual bool isSecure() const       { return false; }
+
+    virtual uint32_t doTransaction(uint32_t flags);
+    virtual void setVisibleRegion(const Region& visibleRegion);
+    virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
+
+private:
+            bool    mCacheDirty;
+    mutable bool    mRefreshCache;
+    mutable bool    mAutoRefreshPending;
+            nsecs_t mCacheAge;
+    mutable GLuint  mTextureName;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_BLUR_H
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
new file mode 100644
index 0000000..00fab70
--- /dev/null
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -0,0 +1,655 @@
+/*
+ * 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 <math.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/StopWatch.h>
+
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+
+#include <ui/PixelFormat.h>
+#include <ui/EGLDisplaySurface.h>
+
+#include "LayerBuffer.h"
+#include "SurfaceFlinger.h"
+#include "VRamHeap.h"
+#include "DisplayHardware/DisplayHardware.h"
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
+const char* const LayerBuffer::typeID = "LayerBuffer";
+
+// ---------------------------------------------------------------------------
+
+LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
+        Client* client, int32_t i)
+    : LayerBaseClient(flinger, display, client, i),
+      mNeedsBlending(false)
+{
+}
+
+LayerBuffer::~LayerBuffer()
+{
+    sp<SurfaceBuffer> s(getClientSurface());
+    if (s != 0) {
+        s->disown();
+        mClientSurface.clear();
+    }
+}
+
+sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const
+{
+    Mutex::Autolock _l(mLock);
+    return mClientSurface.promote();
+}
+
+sp<LayerBaseClient::Surface> LayerBuffer::getSurface() 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;
+}
+
+bool LayerBuffer::needsBlending() const {
+    return mNeedsBlending;
+}
+
+void LayerBuffer::setNeedsBlending(bool blending) {
+    mNeedsBlending = blending;
+}
+
+void LayerBuffer::postBuffer(ssize_t offset)
+{
+    sp<Source> source(getSource());
+    if (source != 0)
+        source->postBuffer(offset);
+}
+
+void LayerBuffer::unregisterBuffers()
+{
+    sp<Source> source(clearSource());
+    if (source != 0)
+        source->unregisterBuffers();
+}
+
+uint32_t LayerBuffer::doTransaction(uint32_t flags)
+{
+    sp<Source> source(getSource());
+    if (source != 0)
+        source->onTransaction(flags);
+    return LayerBase::doTransaction(flags);    
+}
+
+void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
+        Region& outDirtyRegion)
+{
+    // this code-path must be as tight as possible, it's called each time
+    // the screen is composited.
+    sp<Source> source(getSource());
+    if (source != 0)
+        source->onVisibilityResolved(planeTransform);
+    LayerBase::unlockPageFlip(planeTransform, outDirtyRegion);    
+}
+
+void LayerBuffer::onDraw(const Region& clip) const
+{
+    sp<Source> source(getSource());
+    if (LIKELY(source != 0)) {
+        source->onDraw(clip);
+    } else {
+        clearWithOpenGL(clip);
+    }
+}
+
+bool LayerBuffer::transformed() const
+{
+    sp<Source> source(getSource());
+    if (LIKELY(source != 0))
+        return source->transformed();
+    return false;
+}
+
+/**
+ * This creates a "buffer" source for this surface
+ */
+status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
+{
+    Mutex::Autolock _l(mLock);
+    if (mSource != 0)
+        return INVALID_OPERATION;
+
+    sp<BufferSource> source = new BufferSource(*this, buffers);
+
+    status_t result = source->getStatus();
+    if (result == NO_ERROR) {
+        mSource = source;
+    }
+    return result;
+}    
+
+/**
+ * This creates an "overlay" source for this surface
+ */
+sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f)
+{
+    sp<OverlayRef> result;
+    Mutex::Autolock _l(mLock);
+    if (mSource != 0)
+        return result;
+
+    sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f);
+    if (result != 0) {
+        mSource = source;
+    }
+    return result;
+}
+
+sp<LayerBuffer::Source> LayerBuffer::getSource() const {
+    Mutex::Autolock _l(mLock);
+    return mSource;
+}
+
+sp<LayerBuffer::Source> LayerBuffer::clearSource() {
+    sp<Source> source;
+    Mutex::Autolock _l(mLock);
+    source = mSource;
+    mSource.clear();
+    return source;
+}
+
+// ============================================================================
+// LayerBuffer::SurfaceBuffer
+// ============================================================================
+
+LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
+: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
+{
+}
+
+LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
+{
+    unregisterBuffers();
+    mOwner = 0;
+}
+
+status_t LayerBuffer::SurfaceBuffer::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 LayerBaseClient::Surface::onTransact(code, data, reply, flags);
+}
+
+status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
+{
+    LayerBuffer* owner(getOwner());
+    if (owner)
+        return owner->registerBuffers(buffers);
+    return NO_INIT;
+}
+
+void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
+{
+    LayerBuffer* owner(getOwner());
+    if (owner)
+        owner->postBuffer(offset);
+}
+
+void LayerBuffer::SurfaceBuffer::unregisterBuffers()
+{
+    LayerBuffer* owner(getOwner());
+    if (owner)
+        owner->unregisterBuffers();
+}
+
+sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
+        uint32_t w, uint32_t h, int32_t format) {
+    sp<OverlayRef> result;
+    LayerBuffer* owner(getOwner());
+    if (owner)
+        result = owner->createOverlay(w, h, format);
+    return result;
+}
+
+void LayerBuffer::SurfaceBuffer::disown()
+{
+    Mutex::Autolock _l(mLock);
+    mOwner = 0;
+}
+
+// ============================================================================
+// LayerBuffer::Buffer
+// ============================================================================
+
+LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
+    : mBufferHeap(buffers)
+{
+    NativeBuffer& src(mNativeBuffer);
+    src.crop.l = 0;
+    src.crop.t = 0;
+    src.crop.r = buffers.w;
+    src.crop.b = buffers.h;
+    src.img.w = buffers.hor_stride ?: buffers.w;
+    src.img.h = buffers.ver_stride ?: buffers.h;
+    src.img.format = buffers.format;
+    src.img.offset = offset;
+    src.img.base   = buffers.heap->base();
+    src.img.fd     = buffers.heap->heapID();
+}
+
+LayerBuffer::Buffer::~Buffer()
+{
+}
+
+// ============================================================================
+// LayerBuffer::Source
+// LayerBuffer::BufferSource
+// LayerBuffer::OverlaySource
+// ============================================================================
+
+LayerBuffer::Source::Source(LayerBuffer& layer)
+    : mLayer(layer)
+{    
+}
+LayerBuffer::Source::~Source() {    
+}
+void LayerBuffer::Source::onDraw(const Region& clip) const {
+}
+void LayerBuffer::Source::onTransaction(uint32_t flags) {
+}
+void LayerBuffer::Source::onVisibilityResolved(
+        const Transform& planeTransform) {
+}
+void LayerBuffer::Source::postBuffer(ssize_t offset) {
+}
+void LayerBuffer::Source::unregisterBuffers() {
+}
+bool LayerBuffer::Source::transformed() const {
+    return mLayer.mTransformed; 
+}
+
+// ---------------------------------------------------------------------------
+
+LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
+        const ISurface::BufferHeap& buffers)
+    : Source(layer), mStatus(NO_ERROR), 
+      mBufferSize(0), mTextureName(-1U)
+{
+    if (buffers.heap == NULL) {
+        // this is allowed, but in this case, it is illegal to receive
+        // postBuffer(). The surface just erases the framebuffer with
+        // fully transparent pixels.
+        mBufferHeap = buffers;
+        mLayer.setNeedsBlending(false);
+        return;
+    }
+
+    status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT;
+    if (err != NO_ERROR) {
+        LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err));
+        mStatus = err;
+        return;
+    }
+    
+    PixelFormatInfo info;
+    err = getPixelFormatInfo(buffers.format, &info);
+    if (err != NO_ERROR) {
+        LOGE("LayerBuffer::BufferSource: invalid format %d (%s)",
+                buffers.format, strerror(err));
+        mStatus = err;
+        return;
+    }
+
+    if (buffers.hor_stride<0 || buffers.ver_stride<0) {
+        LOGE("LayerBuffer::BufferSource: invalid parameters "
+             "(w=%d, h=%d, xs=%d, ys=%d)", 
+             buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride);
+        mStatus = BAD_VALUE;
+        return;
+    }
+
+    mBufferHeap = buffers;
+    mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);    
+    mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
+    mLayer.forceVisibilityTransaction();
+    
+}
+
+LayerBuffer::BufferSource::~BufferSource()
+{    
+    if (mTextureName != -1U) {
+        LayerBase::deletedTextures.add(mTextureName);
+    }
+}
+
+void LayerBuffer::BufferSource::postBuffer(ssize_t offset)
+{    
+    ISurface::BufferHeap buffers;
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+        buffers = mBufferHeap;
+        if (buffers.heap != 0) {
+            const size_t memorySize = buffers.heap->getSize();
+            if ((size_t(offset) + mBufferSize) > memorySize) {
+                LOGE("LayerBuffer::BufferSource::postBuffer() "
+                     "invalid buffer (offset=%d, size=%d, heap-size=%d",
+                     int(offset), int(mBufferSize), int(memorySize));
+                return;
+            }
+        }
+    }
+
+    sp<Buffer> buffer;
+    if (buffers.heap != 0) {
+        buffer = new LayerBuffer::Buffer(buffers, offset);
+        if (buffer->getStatus() != NO_ERROR)
+            buffer.clear();
+        setBuffer(buffer);
+        mLayer.invalidate();
+    }
+}
+
+void LayerBuffer::BufferSource::unregisterBuffers()
+{
+    Mutex::Autolock _l(mLock);
+    mBufferHeap.heap.clear();
+    mBuffer.clear();
+    mLayer.invalidate();
+}
+
+sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
+{
+    Mutex::Autolock _l(mLock);
+    return mBuffer;
+}
+
+void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
+{
+    Mutex::Autolock _l(mLock);
+    mBuffer = buffer;
+}
+
+bool LayerBuffer::BufferSource::transformed() const
+{
+    return mBufferHeap.transform ? true : Source::transformed(); 
+}
+
+void LayerBuffer::BufferSource::onDraw(const Region& clip) const 
+{
+    sp<Buffer> buffer(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));
+        }
+    }
+
+    if (!can_use_copybit || err) {
+        if (UNLIKELY(mTextureName == -1LU)) {
+            mTextureName = mLayer.createTexture();
+        }
+        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));
+        mLayer.loadTexture(dirty, mTextureName, t, w, h);
+        mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+
+LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
+        sp<OverlayRef>* overlayRef, 
+        uint32_t w, uint32_t h, int32_t format)
+    : Source(layer), mVisibilityChanged(false),
+    mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
+{
+    overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
+    if (overlay_dev == NULL) {
+        // overlays not supported
+        return;
+    }
+
+    mOverlayDevice = overlay_dev;
+    overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);
+    if (overlay == NULL) {
+        // couldn't create the overlay (no memory? no more overlays?)
+        return;
+    }
+
+    // enable dithering...
+    overlay_dev->setParameter(overlay_dev, overlay, 
+            OVERLAY_DITHER, OVERLAY_ENABLE);
+
+    mOverlay = overlay;
+    mWidth = overlay->w;
+    mHeight = overlay->h;
+    mFormat = overlay->format; 
+    mWidthStride = overlay->w_stride;
+    mHeightStride = overlay->h_stride;
+
+    mOverlayHandle = overlay->getHandleRef(overlay);
+    
+    // NOTE: here it's okay to acquire a reference to "this"m as long as
+    // the reference is not released before we leave the ctor.
+    sp<OverlayChannel> channel = new OverlayChannel(this);
+
+    *overlayRef = new OverlayRef(mOverlayHandle, channel,
+            mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
+}
+
+LayerBuffer::OverlaySource::~OverlaySource()
+{
+    if (mOverlay && mOverlayDevice) {
+        overlay_control_device_t* overlay_dev = mOverlayDevice;
+        overlay_dev->destroyOverlay(overlay_dev, mOverlay);
+    }
+}
+
+void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
+{
+    const Layer::State& front(mLayer.drawingState());
+    const Layer::State& temp(mLayer.currentState());
+    if (temp.sequence != front.sequence) {
+        mVisibilityChanged = true;
+    }
+}
+
+void LayerBuffer::OverlaySource::onVisibilityResolved(
+        const Transform& planeTransform)
+{
+    // this code-path must be as tight as possible, it's called each time
+    // the screen is composited.
+    if (UNLIKELY(mOverlay != 0)) {
+        if (mVisibilityChanged) {
+            mVisibilityChanged = false;
+            const Rect& bounds = mLayer.getTransformedBounds();
+            int x = bounds.left;
+            int y = bounds.top;
+            int w = bounds.width();
+            int h = bounds.height();
+            
+            // we need a lock here to protect "destroy"
+            Mutex::Autolock _l(mLock);
+            if (mOverlay) {
+                overlay_control_device_t* overlay_dev = mOverlayDevice;
+                overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
+                overlay_dev->setParameter(overlay_dev, mOverlay, 
+                        OVERLAY_TRANSFORM, mLayer.getOrientation());
+            }
+        }
+    }
+}
+
+void LayerBuffer::OverlaySource::serverDestroy() 
+{
+    mLayer.clearSource();
+    destroyOverlay();
+}
+
+void LayerBuffer::OverlaySource::destroyOverlay() 
+{
+    // we need a lock here to protect "onVisibilityResolved"
+    Mutex::Autolock _l(mLock);
+    if (mOverlay) {
+        overlay_control_device_t* overlay_dev = mOverlayDevice;
+        overlay_dev->destroyOverlay(overlay_dev, mOverlay);
+        mOverlay = 0;
+    }
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
new file mode 100644
index 0000000..2dc77f1
--- /dev/null
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -0,0 +1,216 @@
+/*
+ * 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_LAYER_BUFFER_H
+#define ANDROID_LAYER_BUFFER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/IMemory.h>
+#include <private/ui/LayerState.h>
+#include <EGL/eglnatives.h>
+
+#include "LayerBase.h"
+#include "LayerBitmap.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class MemoryDealer;
+class Region;
+class OverlayRef;
+
+class LayerBuffer : public LayerBaseClient
+{
+    class Source : public LightRefBase<Source> {
+    public:
+        Source(LayerBuffer& layer);
+        virtual ~Source();
+        virtual void onDraw(const Region& clip) const;
+        virtual void onTransaction(uint32_t flags);
+        virtual void onVisibilityResolved(const Transform& planeTransform);
+        virtual void postBuffer(ssize_t offset);
+        virtual void unregisterBuffers();
+        virtual bool transformed() const;
+    protected:
+        LayerBuffer& mLayer;
+    };
+
+
+public:
+    static const uint32_t typeInfo;
+    static const char* const typeID;
+    virtual char const* getTypeID() const { return typeID; }
+    virtual uint32_t getTypeInfo() const { return typeInfo; }
+
+            LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
+                        Client* client, int32_t i);
+        virtual ~LayerBuffer();
+
+    virtual bool needsBlending() const;
+
+    virtual sp<LayerBaseClient::Surface> getSurface() const;
+    virtual void onDraw(const Region& clip) const;
+    virtual uint32_t doTransaction(uint32_t flags);
+    virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
+    virtual bool transformed() const;
+
+    status_t registerBuffers(const ISurface::BufferHeap& buffers);
+    void postBuffer(ssize_t offset);
+    void unregisterBuffers();
+    sp<OverlayRef> createOverlay(uint32_t w, uint32_t h, int32_t format);
+    
+    sp<Source> getSource() const;
+    sp<Source> clearSource();
+    void setNeedsBlending(bool blending);
+    const Rect& getTransformedBounds() const {
+        return mTransformedBounds;
+    }
+
+private:
+    struct NativeBuffer {
+        copybit_image_t   img;
+        copybit_rect_t    crop;
+    };
+
+    class Buffer : public LightRefBase<Buffer> {
+    public:
+        Buffer(const ISurface::BufferHeap& buffers, ssize_t offset);
+        inline status_t getStatus() const {
+            return mBufferHeap.heap!=0 ? NO_ERROR : NO_INIT;
+        }
+        inline const NativeBuffer& getBuffer() const {
+            return mNativeBuffer;
+        }
+    protected:
+        friend class LightRefBase<Buffer>;
+        Buffer& operator = (const Buffer& rhs);
+        Buffer(const Buffer& rhs);
+        ~Buffer();
+    private:
+        ISurface::BufferHeap    mBufferHeap;
+        NativeBuffer            mNativeBuffer;
+    };
+
+    class BufferSource : public Source {
+    public:
+        BufferSource(LayerBuffer& layer, const ISurface::BufferHeap& buffers);
+        virtual ~BufferSource();
+
+        status_t getStatus() const { return mStatus; }
+        sp<Buffer> getBuffer() const;
+        void setBuffer(const sp<Buffer>& buffer);
+
+        virtual void onDraw(const Region& clip) const;
+        virtual void postBuffer(ssize_t offset);
+        virtual void unregisterBuffers();
+        virtual bool transformed() const;
+    private:
+        mutable Mutex   mLock;
+        sp<Buffer>      mBuffer;
+        status_t        mStatus;
+        ISurface::BufferHeap mBufferHeap;
+        size_t          mBufferSize;
+        mutable sp<MemoryDealer> mTemporaryDealer;
+        mutable LayerBitmap mTempBitmap;
+        mutable GLuint  mTextureName;
+    };
+    
+    class OverlaySource : public Source {
+    public:
+        OverlaySource(LayerBuffer& layer,
+                sp<OverlayRef>* overlayRef, 
+                uint32_t w, uint32_t h, int32_t format);
+        virtual ~OverlaySource();
+        virtual void onTransaction(uint32_t flags);
+        virtual void onVisibilityResolved(const Transform& planeTransform);
+    private:
+        void serverDestroy(); 
+        void destroyOverlay(); 
+        class OverlayChannel : public BnOverlay {
+            mutable Mutex mLock;
+            sp<OverlaySource> mSource;
+            virtual void destroy() {
+                sp<OverlaySource> source;
+                { // scope for the lock;
+                    Mutex::Autolock _l(mLock);
+                    source = mSource;
+                    mSource.clear();
+                }
+                if (source != 0) {
+                    source->serverDestroy();
+                }
+            }
+        public:
+            OverlayChannel(const sp<OverlaySource>& source)
+                : mSource(source) {
+            }
+        };
+        friend class OverlayChannel;
+        bool mVisibilityChanged;
+
+        overlay_t* mOverlay;        
+        overlay_handle_t mOverlayHandle;
+        overlay_control_device_t* mOverlayDevice;
+        uint32_t mWidth;
+        uint32_t mHeight;
+        int32_t mFormat;
+        int32_t mWidthStride;
+        int32_t mHeightStride;
+        mutable Mutex mLock;
+    };
+
+
+    class SurfaceBuffer : public LayerBaseClient::Surface
+    {
+    public:
+                SurfaceBuffer(SurfaceID id, 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;
+        }
+        mutable Mutex   mLock;
+        LayerBuffer*    mOwner;
+    };
+
+    friend class SurfaceFlinger;
+    sp<SurfaceBuffer>   getClientSurface() const;
+
+    mutable Mutex   mLock;
+    sp<Source>      mSource;
+
+    bool            mInvalidate;
+    bool            mNeedsBlending;
+    mutable wp<SurfaceBuffer> mClientSurface;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_BUFFER_H
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
new file mode 100644
index 0000000..0c347cc
--- /dev/null
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -0,0 +1,113 @@
+/*
+ * 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 "LayerDim.h"
+#include "SurfaceFlinger.h"
+#include "VRamHeap.h"
+#include "DisplayHardware/DisplayHardware.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10;
+const char* const LayerDim::typeID = "LayerDim";
+sp<MemoryDealer> LayerDim::mDimmerDealer;
+LayerBitmap LayerDim::mDimmerBitmap;
+
+// ---------------------------------------------------------------------------
+
+LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
+        Client* client, int32_t i)
+     : LayerBaseClient(flinger, display, client, i)
+{
+}
+
+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()
+{
+}
+
+void LayerDim::onDraw(const Region& clip) const
+{
+    const State& s(drawingState());
+
+    Region::iterator iterator(clip);
+    if (s.alpha>0 && iterator) {
+        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); 
+            }
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h
new file mode 100644
index 0000000..3e37a47
--- /dev/null
+++ b/libs/surfaceflinger/LayerDim.h
@@ -0,0 +1,57 @@
+/*
+ * 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_LAYER_DIM_H
+#define ANDROID_LAYER_DIM_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "LayerBase.h"
+#include "LayerBitmap.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class LayerDim : public LayerBaseClient
+{
+public:    
+    static const uint32_t typeInfo;
+    static const char* const typeID;
+    virtual char const* getTypeID() const { return typeID; }
+    virtual uint32_t getTypeInfo() const { return typeInfo; }
+    
+                LayerDim(SurfaceFlinger* flinger, DisplayID display,
+                        Client* client, int32_t i);
+        virtual ~LayerDim();
+
+    virtual void onDraw(const Region& clip) const;
+    virtual bool needsBlending() const  { return true; }
+    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;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_DIM_H
diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp
new file mode 100644
index 0000000..2b72d7c
--- /dev/null
+++ b/libs/surfaceflinger/LayerOrientationAnim.cpp
@@ -0,0 +1,287 @@
+/*
+ * 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 "LayerOrientationAnim.h"
+#include "SurfaceFlinger.h"
+#include "DisplayHardware/DisplayHardware.h"
+#include "OrientationAnimation.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80;
+const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim";
+
+// ---------------------------------------------------------------------------
+
+LayerOrientationAnim::LayerOrientationAnim(
+        SurfaceFlinger* flinger, DisplayID display, 
+        OrientationAnimation* anim, 
+        const LayerBitmap& bitmap,
+        const LayerBitmap& bitmapIn)
+    : LayerBase(flinger, display), mAnim(anim), 
+      mBitmap(bitmap), mBitmapIn(bitmapIn), 
+      mTextureName(-1), mTextureNameIn(-1)
+{
+    mStartTime = systemTime();
+    mFinishTime = 0;
+    mOrientationCompleted = false;
+    mFirstRedraw = false;
+    mLastNormalizedTime = 0;
+    mLastScale = 0;
+    mNeedsBlending = false;
+}
+
+LayerOrientationAnim::~LayerOrientationAnim()
+{
+    if (mTextureName != -1U) {
+        LayerBase::deletedTextures.add(mTextureName);
+    }
+    if (mTextureNameIn != -1U) {
+        LayerBase::deletedTextures.add(mTextureNameIn);
+    }
+}
+
+bool LayerOrientationAnim::needsBlending() const 
+{
+    return mNeedsBlending; 
+}
+
+Point LayerOrientationAnim::getPhysicalSize() const
+{
+    const GraphicPlane& plane(graphicPlane(0));
+    const DisplayHardware& hw(plane.displayHardware());
+    return Point(hw.getWidth(), hw.getHeight());
+}
+
+void LayerOrientationAnim::validateVisibility(const Transform&)
+{
+    const Layer::State& s(drawingState());
+    const Transform tr(s.transform);
+    const Point size(getPhysicalSize());
+    uint32_t w = size.x;
+    uint32_t h = size.y;
+    mTransformedBounds = tr.makeBounds(w, h);
+    mLeft = tr.tx();
+    mTop  = tr.ty();
+    transparentRegionScreen.clear();
+    mTransformed = true;
+    mCanUseCopyBit = false;
+    copybit_device_t* copybit = mFlinger->getBlitEngine();
+    if (copybit) { 
+        mCanUseCopyBit = true;
+    }
+}
+
+void LayerOrientationAnim::onOrientationCompleted()
+{
+    mFinishTime = systemTime();
+    mOrientationCompleted = true;
+    mFirstRedraw = true;
+    mNeedsBlending = true;
+    mFlinger->invalidateLayerVisibility(this);
+}
+
+void LayerOrientationAnim::onDraw(const Region& clip) const
+{
+    // Animation...
+    const float MIN_SCALE = 0.5f;
+    const float DURATION = ms2ns(200);
+    const float BOUNCES_PER_SECOND = 1.618f;
+    const float BOUNCES_AMPLITUDE = 1.0f/32.0f;
+
+    const nsecs_t now = systemTime();
+    float scale, alpha;
+    
+    if (mOrientationCompleted) {
+        if (mFirstRedraw) {
+            mFirstRedraw = false;
+            
+            // make a copy of what's on screen
+            copybit_image_t image;
+            mBitmapIn.getBitmapSurface(&image);
+            const DisplayHardware& hw(graphicPlane(0).displayHardware());
+            hw.copyBackToImage(image);
+
+            // and erase the screen for this round
+            glDisable(GL_BLEND);
+            glDisable(GL_DITHER);
+            glDisable(GL_SCISSOR_TEST);
+            glClearColor(0,0,0,0);
+            glClear(GL_COLOR_BUFFER_BIT);
+            
+            // FIXME: code below is gross
+            mNeedsBlending = false;
+            LayerOrientationAnim* self(const_cast<LayerOrientationAnim*>(this));
+            mFlinger->invalidateLayerVisibility(self);
+        }
+
+        // make sure pick-up where we left off
+        const float duration = DURATION * mLastNormalizedTime;
+        const float normalizedTime = (float(now - mFinishTime) / duration);
+        if (normalizedTime <= 1.0f) {
+            const float squaredTime = normalizedTime*normalizedTime;
+            scale = (1.0f - mLastScale)*squaredTime + mLastScale;
+            alpha = (1.0f - normalizedTime);
+            alpha *= alpha;
+            alpha *= alpha;
+        } else {
+            mAnim->onAnimationFinished();
+            scale = 1.0f;
+            alpha = 0.0f;
+        }
+    } else {
+        const float normalizedTime = float(now - mStartTime) / DURATION;
+        if (normalizedTime <= 1.0f) {
+            mLastNormalizedTime = normalizedTime;
+            const float squaredTime = normalizedTime*normalizedTime;
+            scale = (MIN_SCALE-1.0f)*squaredTime + 1.0f;
+            alpha = 1.0f;
+        } else {
+            mLastNormalizedTime = 1.0f;
+            const float to_seconds = DURATION / seconds(1);
+            const float phi = BOUNCES_PER_SECOND * 
+                    (((normalizedTime - 1.0f) * to_seconds)*M_PI*2);
+            scale = MIN_SCALE + BOUNCES_AMPLITUDE * (1.0f - cosf(phi));
+            alpha = 1.0f;
+        }
+        mLastScale = scale;
+    }
+    drawScaled(scale, alpha);
+}
+
+void LayerOrientationAnim::drawScaled(float f, float alpha) const
+{
+    copybit_image_t dst;
+    const GraphicPlane& plane(graphicPlane(0));
+    const DisplayHardware& hw(plane.displayHardware());
+    hw.getDisplaySurface(&dst);
+
+    // clear screen
+    // TODO: with update on demand, we may be able 
+    // to not erase the screen at all during the animation 
+    if (!mOrientationCompleted) {
+        glDisable(GL_BLEND);
+        glDisable(GL_DITHER);
+        glDisable(GL_SCISSOR_TEST);
+        glClearColor(0,0,0,0);
+        glClear(GL_COLOR_BUFFER_BIT);
+    }
+    
+    const int w = dst.w*f; 
+    const int h = dst.h*f; 
+    const int xc = uint32_t(dst.w-w)/2;
+    const int yc = uint32_t(dst.h-h)/2;
+    const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; 
+
+    copybit_image_t src;
+    mBitmap.getBitmapSurface(&src);
+    const copybit_rect_t srect = { 0, 0, src.w, src.h };
+
+    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 (alpha < 1.0f) {
+            copybit_image_t srcIn;
+            mBitmapIn.getBitmapSurface(&srcIn);
+            region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b )));
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+            err = copybit->stretch(copybit, &dst, &srcIn, &drect, &srect, &it);
+        }
+
+        if (!err && alpha > 0.0f) {
+            region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b )));
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alpha*255));
+            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+        }
+        LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err));
+    }
+    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;
+        t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
+
+        Transform tr;
+        tr.set(f,0,0,f);
+        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 (alpha < 1.0f) {
+            copybit_image_t src;
+            mBitmapIn.getBitmapSurface(&src);
+            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 = 255;
+            const Region clip(Rect( drect.l, drect.t, drect.r, drect.b ));
+            drawWithOpenGL(clip, mTextureName, t);
+        }
+
+        t.data = (GGLubyte*)(intptr_t(src.base) + src.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(alpha*255);
+        const Region clip(Rect( drect.l, drect.t, drect.r, drect.b ));
+        drawWithOpenGL(clip, mTextureName, t);
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h
new file mode 100644
index 0000000..7367685
--- /dev/null
+++ b/libs/surfaceflinger/LayerOrientationAnim.h
@@ -0,0 +1,75 @@
+/*
+ * 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_LAYER_ORIENTATION_ANIM_H
+#define ANDROID_LAYER_ORIENTATION_ANIM_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+#include <utils/Parcel.h>
+
+#include "LayerBase.h"
+#include "LayerBitmap.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+class OrientationAnimation;
+
+class LayerOrientationAnim : public LayerBase
+{
+public:    
+    static const uint32_t typeInfo;
+    static const char* const typeID;
+    virtual char const* getTypeID() const { return typeID; }
+    virtual uint32_t getTypeInfo() const { return typeInfo; }
+    
+                LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display,
+                        OrientationAnimation* anim, 
+                        const LayerBitmap& zoomOut,
+                        const LayerBitmap& zoomIn);
+        virtual ~LayerOrientationAnim();
+
+            void onOrientationCompleted();
+
+    virtual void onDraw(const Region& clip) const;
+    virtual Point getPhysicalSize() const;
+    virtual void validateVisibility(const Transform& globalTransform);
+    virtual bool needsBlending() const;
+    virtual bool isSecure() const       { return false; }
+private:
+    void drawScaled(float scale, float alpha) const;
+
+    OrientationAnimation* mAnim;
+    LayerBitmap mBitmap;
+    LayerBitmap mBitmapIn;
+    nsecs_t mStartTime;
+    nsecs_t mFinishTime;
+    bool mOrientationCompleted;
+    mutable bool mFirstRedraw;
+    mutable float mLastNormalizedTime;
+    mutable float mLastScale;
+    mutable GLuint  mTextureName;
+    mutable GLuint  mTextureNameIn;
+    mutable bool mNeedsBlending;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_ORIENTATION_ANIM_H
diff --git a/libs/surfaceflinger/MODULE_LICENSE_APACHE2 b/libs/surfaceflinger/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/surfaceflinger/MODULE_LICENSE_APACHE2
diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp
new file mode 100644
index 0000000..f6f1326
--- /dev/null
+++ b/libs/surfaceflinger/OrientationAnimation.cpp
@@ -0,0 +1,155 @@
+/*
+ * 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 <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include "LayerOrientationAnim.h"
+#include "OrientationAnimation.h"
+#include "SurfaceFlinger.h"
+#include "VRamHeap.h"
+
+#include "DisplayHardware/DisplayHardware.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+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()
+{
+}
+
+void OrientationAnimation::onOrientationChanged()
+{
+    if (mState == DONE)
+        mState = PREPARE;
+}
+
+void OrientationAnimation::onAnimationFinished()
+{
+    if (mState != DONE)
+        mState = FINISH;
+}
+
+bool OrientationAnimation::run_impl()
+{
+    bool skip_frame;
+    switch (mState) {
+        default:
+        case DONE:
+            skip_frame = done();
+            break;
+        case PREPARE:
+            skip_frame = prepare();
+            break;
+        case PHASE1:
+            skip_frame = phase1();
+            break;
+        case PHASE2:
+            skip_frame = phase2();
+            break;
+        case FINISH:
+            skip_frame = finished();
+            break;
+    }
+    return skip_frame;
+}
+
+bool OrientationAnimation::done()
+{
+    if (mFlinger->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 true;
+    }
+    return false;
+}
+
+bool OrientationAnimation::prepare()
+{
+    mState = PHASE1;
+    
+    const GraphicPlane& plane(mFlinger->graphicPlane(0));
+    const DisplayHardware& hw(plane.displayHardware());
+    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());
+
+    copybit_image_t front;
+    bitmap.getBitmapSurface(&front);
+    hw.copyFrontToImage(front);
+
+    LayerOrientationAnim* l = new LayerOrientationAnim(
+            mFlinger.get(), 0, this, bitmap, bitmapIn);
+    l->initStates(w, h, 0);
+    l->setLayer(INT_MAX-1);
+    mFlinger->addLayer(l);
+    mLayerOrientationAnim = l;
+    return true;
+}
+
+bool OrientationAnimation::phase1()
+{
+    if (mFlinger->isFrozen() == false) {
+        // start phase 2
+        mState = PHASE2;
+        mLayerOrientationAnim->onOrientationCompleted();
+        mLayerOrientationAnim->invalidate();
+        return true;
+        
+    }
+    mLayerOrientationAnim->invalidate();
+    return false;
+}
+
+bool OrientationAnimation::phase2()
+{
+    // do the 2nd phase of the animation
+    mLayerOrientationAnim->invalidate();
+    return false;
+}
+
+bool OrientationAnimation::finished()
+{
+    mState = DONE;
+    mFlinger->removeLayer(mLayerOrientationAnim);
+    mLayerOrientationAnim = NULL;
+    return true;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h
new file mode 100644
index 0000000..ba33fce
--- /dev/null
+++ b/libs/surfaceflinger/OrientationAnimation.h
@@ -0,0 +1,73 @@
+/*
+ * 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_ORIENTATION_ANIMATION_H
+#define ANDROID_ORIENTATION_ANIMATION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class SurfaceFlinger;
+class MemoryDealer;
+class LayerOrientationAnim;
+
+class OrientationAnimation
+{
+public:    
+                 OrientationAnimation(const sp<SurfaceFlinger>& flinger);
+        virtual ~OrientationAnimation();
+
+   void onOrientationChanged();
+   void onAnimationFinished();
+   inline bool run() {
+       if (LIKELY(mState == DONE))
+           return false;
+       return run_impl();
+   }
+
+private:
+    enum {
+        DONE = 0,
+        PREPARE,
+        PHASE1,
+        PHASE2,
+        FINISH
+    };
+
+    bool run_impl();
+    bool done();
+    bool prepare();
+    bool phase1();
+    bool phase2();
+    bool finished();
+
+    sp<SurfaceFlinger> mFlinger;
+    sp<MemoryDealer> mTemporaryDealer;
+    LayerOrientationAnim* mLayerOrientationAnim;
+    int mState;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_ORIENTATION_ANIMATION_H
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
new file mode 100644
index 0000000..900282a
--- /dev/null
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -0,0 +1,1840 @@
+/*
+ * 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 <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/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+#include <utils/MemoryDealer.h>
+#include <utils/MemoryBase.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/StopWatch.h>
+
+#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 "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"
+
+
+#define DISPLAY_COUNT       1
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+void SurfaceFlinger::instantiate() {
+    defaultServiceManager()->addService(
+            String16("SurfaceFlinger"), new SurfaceFlinger());
+}
+
+void SurfaceFlinger::shutdown() {
+    // we should unregister here, but not really because
+    // when (if) the service manager goes away, all the services
+    // it has a reference to will leave too.
+}
+
+// ---------------------------------------------------------------------------
+
+SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs)
+    : lookup(rhs.lookup), layers(rhs.layers)
+{
+}
+
+ssize_t SurfaceFlinger::LayerVector::indexOf(
+        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,
+            "LayerVector[%p]: layers[%d]=%p, key=%p",
+            this, int(idx), layers[idx], key);
+        return idx;
+    }
+    return i;
+}
+
+ssize_t SurfaceFlinger::LayerVector::add(
+        LayerBase* layer,
+        Vector<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();
+    while (l <= h) {
+        mid = l + (h - l)/2;
+        const int c = cmp(a+mid, &layer);
+        if (c == 0)     { l = mid; break; }
+        else if (c<0)   { l = mid+1; }
+        else            { h = mid-1; }
+    }
+    size_t order = l;
+    while (order<count && !cmp(&layer, a+order)) {
+        order++;
+    }
+    count = lookup.size();
+    for (size_t i=0 ; i<count ; i++) {
+        if (lookup.valueAt(i) >= order) {
+            lookup.editValueAt(i)++;
+        }
+    }
+    layers.insertAt(layer, order);
+    lookup.add(layer, order);
+    return order;
+}
+
+ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer)
+{
+    const ssize_t keyIndex = lookup.indexOfKey(layer);
+    if (keyIndex >= 0) {
+        const size_t index = lookup.valueAt(keyIndex);
+        LOG_ASSERT(layers[index]==layer,
+                "LayerVector[%p]: layers[%u]=%p, layer=%p",
+                this, int(index), layers[index], layer);
+        layers.removeItemsAt(index);
+        lookup.removeItemsAt(keyIndex);
+        const size_t count = lookup.size();
+        for (size_t i=0 ; i<count ; i++) {
+            if (lookup.valueAt(i) >= size_t(index)) {
+                lookup.editValueAt(i)--;
+            }
+        }
+        return index;
+    }
+    return NAME_NOT_FOUND;
+}
+
+ssize_t SurfaceFlinger::LayerVector::reorder(
+        LayerBase* layer,
+        Vector<LayerBase*>::compar_t cmp)
+{
+    // XXX: it's a little lame. but oh well...
+    ssize_t err = remove(layer);
+    if (err >=0)
+        err = add(layer, cmp);
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+#if 0
+#pragma mark -
+#endif
+
+SurfaceFlinger::SurfaceFlinger()
+    :   BnSurfaceComposer(), Thread(false),
+        mTransactionFlags(0),
+        mTransactionCount(0),
+        mBootTime(systemTime()),
+        mLastScheduledBroadcast(NULL),
+        mVisibleRegionsDirty(false),
+        mDeferReleaseConsole(false),
+        mFreezeDisplay(false),
+        mFreezeCount(0),
+        mDebugRegion(0),
+        mDebugCpu(0),
+        mDebugFps(0),
+        mDebugBackground(0),
+        mDebugNoBootAnimation(0),
+        mSyncObject(),
+        mDeplayedTransactionPending(0),
+        mConsoleSignals(0),
+        mSecureFrameBuffer(0)
+{
+    init();
+}
+
+void SurfaceFlinger::init()
+{
+    LOGI("SurfaceFlinger is starting");
+
+    // debugging stuff...
+    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);
+    property_get("debug.sf.nobootanimation", value, "0");
+    mDebugNoBootAnimation = atoi(value);
+
+    LOGI_IF(mDebugRegion,           "showupdates enabled");
+    LOGI_IF(mDebugCpu,              "showcpu enabled");
+    LOGI_IF(mDebugBackground,       "showbackground enabled");
+    LOGI_IF(mDebugFps,              "showfps enabled");
+    LOGI_IF(mDebugNoBootAnimation,  "boot animation disabled");
+}
+
+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
+{
+    return graphicPlane(0).displayHardware().getOverlayEngine();
+}
+
+sp<IMemory> SurfaceFlinger::getCblk() const
+{
+    return mServerCblkMemory;
+}
+
+status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback,
+        gpu_info_t* gpu)
+{
+    IPCThreadState* ipc = IPCThreadState::self();
+    const int pid = ipc->getCallingPid();
+    status_t err = mGPU->request(pid, callback, gpu);
+    return err;
+}
+
+status_t SurfaceFlinger::revokeGPU()
+{
+    return mGPU->friendlyRevoke();
+}
+
+sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
+{
+    Mutex::Autolock _l(mStateLock);
+    uint32_t token = mTokens.acquire();
+
+    Client* client = new Client(token, this);
+    if ((client == 0) || (client->ctrlblk == 0)) {
+        mTokens.release(token);
+        return 0;
+    }
+    status_t err = mClientsMap.add(token, client);
+    if (err < 0) {
+        delete client;
+        mTokens.release(token);
+        return 0;
+    }
+    sp<BClient> bclient =
+        new BClient(this, token, client->controlBlockMemory());
+    return bclient;
+}
+
+void SurfaceFlinger::destroyConnection(ClientID cid)
+{
+    Mutex::Autolock _l(mStateLock);
+    Client* const client = mClientsMap.valueFor(cid);
+    if (client) {
+        // free all the layers this client owns
+        const Vector<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);
+        }
+
+        // the resources associated with this client will be freed
+        // during the next transaction, after these surfaces have been
+        // properly removed from the screen
+
+        // remove this client from our ClientID->Client mapping.
+        mClientsMap.removeItem(cid);
+
+        // and add it to the list of disconnected clients
+        mDisconnectedClients.add(client);
+
+        // request a transaction
+        setTransactionFlags(eTransactionNeeded);
+    }
+}
+
+const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
+{
+    LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
+    const GraphicPlane& plane(mGraphicPlanes[dpy]);
+    return plane;
+}
+
+GraphicPlane& SurfaceFlinger::graphicPlane(int dpy)
+{
+    return const_cast<GraphicPlane&>(
+        const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));
+}
+
+void SurfaceFlinger::bootFinished()
+{
+    const nsecs_t now = systemTime();
+    const nsecs_t duration = now - mBootTime;
+    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
+    if (mBootAnimation != 0) {
+        mBootAnimation->requestExit();
+        mBootAnimation.clear();
+    }
+}
+
+void SurfaceFlinger::onFirstRef()
+{
+    run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
+
+    // Wait for the main thread to be done with its initialization
+    mReadyToRunBarrier.wait();
+}
+
+
+static inline uint16_t pack565(int r, int g, int b) {
+    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. "
+            "Initializing graphics H/W...");
+
+    // create the shared control-block
+    mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY);
+    LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
+
+    mServerCblkMemory = mServerHeap->allocate(4096);
+    LOGE_IF(mServerCblkMemory==0, "can't create shared control block");
+
+    mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer());
+    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;
+
+    {
+        // initialize the main display
+        GraphicPlane& plane(graphicPlane(dpy));
+        DisplayHardware* const hw = new DisplayHardware(this, dpy);
+        plane.setDisplayHardware(hw);
+    }
+
+    // initialize primary screen
+    // (other display should be initialized in the same manner, but
+    // asynchronously, as they could come and go. None of this is supported
+    // yet).
+    const GraphicPlane& plane(graphicPlane(dpy));
+    const DisplayHardware& hw = plane.displayHardware();
+    const uint32_t w = hw.getWidth();
+    const uint32_t h = hw.getHeight();
+    const uint32_t f = hw.getFormat();
+    hw.makeCurrent();
+
+    // initialize the shared control block
+    mServerCblk->connected |= 1<<dpy;
+    display_cblk_t* dcblk = mServerCblk->displays + dpy;
+    memset(dcblk, 0, sizeof(display_cblk_t));
+    dcblk->w            = w;
+    dcblk->h            = h;
+    dcblk->format       = f;
+    dcblk->orientation  = ISurfaceComposer::eOrientationDefault;
+    dcblk->xdpi         = hw.getDpiX();
+    dcblk->ydpi         = hw.getDpiY();
+    dcblk->fps          = hw.getRefreshRate();
+    dcblk->density      = hw.getDensity();
+    asm volatile ("":::"memory");
+
+    // Initialize OpenGL|ES
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+    glPixelStorei(GL_PACK_ALIGNMENT, 4); 
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glEnable(GL_SCISSOR_TEST);
+    glShadeModel(GL_FLAT);
+    glDisable(GL_DITHER);
+    glDisable(GL_CULL_FACE);
+
+    const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
+    const uint16_t g1 = pack565(0x17,0x2f,0x17);
+    const uint16_t textureData[4] = { g0, g1, g1, g0 };
+    glGenTextures(1, &mWormholeTexName);
+    glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
+            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);
+
+    glViewport(0, 0, w, h);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrthof(0, w, h, 0, 0, 1);
+
+   LayerDim::initDimmer(this, w, h);
+
+    mReadyToRunBarrier.open();
+
+    /*
+     *  We're now ready to accept clients...
+     */
+
+    mOrientationAnimation = new OrientationAnimation(this);
+    
+    // start CPU gauge display
+    if (mDebugCpu)
+        mCpuGauge = new CPUGauge(this, ms2ns(500));
+
+    // the boot animation!
+    if (mDebugNoBootAnimation == false)
+        mBootAnimation = new BootAnimation(this);
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+#if 0
+#pragma mark -
+#pragma mark Events Handler
+#endif
+
+void SurfaceFlinger::waitForEvent()
+{
+    // wait for something to do
+    if (UNLIKELY(isFrozen())) {
+        // wait 5 seconds
+        int err = mSyncObject.wait(ms2ns(5000));
+        if (err != NO_ERROR) {
+            if (isFrozen()) {
+                // we timed out and are still frozen
+                LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
+                        mFreezeDisplay, mFreezeCount);
+                mFreezeCount = 0;
+            }
+        }
+    } else {
+        mSyncObject.wait();
+    }
+}
+
+void SurfaceFlinger::signalEvent() {
+    mSyncObject.open();
+}
+
+void SurfaceFlinger::signal() const {
+    mSyncObject.open();
+}
+
+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);
+    }
+}
+
+// ----------------------------------------------------------------------------
+#if 0
+#pragma mark -
+#pragma mark Main loop
+#endif
+
+bool SurfaceFlinger::threadLoop()
+{
+    waitForEvent();
+
+    // check for transactions
+    if (UNLIKELY(mConsoleSignals)) {
+        handleConsoleEvents();
+    }
+
+    if (LIKELY(mTransactionCount == 0)) {
+        // if we're in a global transaction, don't do anything.
+        const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+        uint32_t transactionFlags = getTransactionFlags(mask);
+        if (LIKELY(transactionFlags)) {
+            handleTransaction(transactionFlags);
+        }
+    }
+
+    // post surfaces (if needed)
+    handlePageFlip();
+
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    if (LIKELY(hw.canDraw())) {
+        // repaint the framebuffer (if needed)
+        handleRepaint();
+
+        // release the clients before we flip ('cause flip might block)
+        unlockClients();
+        executeScheduledBroadcasts();
+
+        // sample the cpu gauge
+        if (UNLIKELY(mDebugCpu)) {
+            handleDebugCpu();
+        }
+
+        postFramebuffer();
+    } else {
+        // pretend we did the post
+        unlockClients();
+        executeScheduledBroadcasts();
+        usleep(16667); // 60 fps period
+    }
+    return true;
+}
+
+void SurfaceFlinger::postFramebuffer()
+{
+    const bool skip = mOrientationAnimation->run();
+    if (UNLIKELY(skip)) {
+        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();
+        }
+    }
+}
+
+void SurfaceFlinger::handleConsoleEvents()
+{
+    // something to do with the console
+    const DisplayHardware& hw = graphicPlane(0).displayHardware();
+
+    int what = android_atomic_and(0, &mConsoleSignals);
+    if (what & eConsoleAcquired) {
+        hw.acquireScreen();
+    }
+
+    if (mDeferReleaseConsole && hw.canDraw()) {
+        // We got the release signal before the aquire signal
+        mDeferReleaseConsole = false;
+        revokeGPU();
+        hw.releaseScreen();
+    }
+
+    if (what & eConsoleReleased) {
+        if (hw.canDraw()) {
+            revokeGPU();
+            hw.releaseScreen();
+        } else {
+            mDeferReleaseConsole = true;
+        }
+    }
+
+    mDirtyRegion.set(hw.bounds());
+}
+
+void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
+{
+    Mutex::Autolock _l(mStateLock);
+
+    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+    const size_t count = currentLayers.size();
+
+    /*
+     * Traversal of the children
+     * (perform the transaction for each of them if needed)
+     */
+
+    const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
+    if (layersNeedTransaction) {
+        for (size_t i=0 ; i<count ; i++) {
+            LayerBase* const layer = currentLayers[i];
+            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
+            if (!trFlags) continue;
+
+            const uint32_t flags = layer->doTransaction(0);
+            if (flags & Layer::eVisibleRegion)
+                mVisibleRegionsDirty = true;
+
+            if (flags & Layer::eRestartTransaction) {
+                // restart the transaction, but back-off a little
+                layer->setTransactionFlags(eTransactionNeeded);
+                setTransactionFlags(eTraversalNeeded, ms2ns(8));
+            }
+        }
+    }
+
+    /*
+     * Perform our own transaction if needed
+     */
+
+    if (transactionFlags & eTransactionNeeded) {
+        if (mCurrentState.orientation != mDrawingState.orientation) {
+            // the orientation has changed, recompute all visible regions
+            // and invalidate everything.
+
+            const int dpy = 0;
+            const int orientation = mCurrentState.orientation;
+            GraphicPlane& plane(graphicPlane(dpy));
+            plane.setOrientation(orientation);
+
+            // update the shared control block
+            const DisplayHardware& hw(plane.displayHardware());
+            volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
+            dcblk->orientation = orientation;
+            if (orientation & eOrientationSwapMask) {
+                // 90 or 270 degrees orientation
+                dcblk->w = hw.getHeight();
+                dcblk->h = hw.getWidth();
+            } else {
+                dcblk->w = hw.getWidth();
+                dcblk->h = hw.getHeight();
+            }
+
+            mVisibleRegionsDirty = true;
+            mDirtyRegion.set(hw.bounds());
+
+            mOrientationAnimation->onOrientationChanged();
+        }
+
+        if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
+            // freezing or unfreezing the display -> trigger animation if needed
+            mFreezeDisplay = mCurrentState.freezeDisplay;
+            const nsecs_t now = systemTime();
+            if (mFreezeDisplay) {
+                mFreezeDisplayTime = now;
+            } else {
+                //LOGD("Screen was frozen for %llu us",
+                //        ns2us(now-mFreezeDisplayTime));
+            }
+        }
+
+        // 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;
+        }
+
+        // get rid of all resources we don't need anymore
+        // (layers and clients)
+        free_resources_l();
+    }
+
+    commitTransaction();
+}
+
+sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
+{
+    return new FreezeLock(const_cast<SurfaceFlinger *>(this));
+}
+
+void SurfaceFlinger::computeVisibleRegions(
+    LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
+{
+    const GraphicPlane& plane(graphicPlane(0));
+    const Transform& planeTransform(plane.transform());
+
+    Region aboveOpaqueLayers;
+    Region aboveCoveredLayers;
+    Region dirty;
+
+    bool secureFrameBuffer = false;
+
+    size_t i = currentLayers.size();
+    while (i--) {
+        LayerBase* const layer = currentLayers[i];
+        layer->validateVisibility(planeTransform);
+
+        // start with the whole surface at its current location
+        const Layer::State& s = layer->drawingState();
+        const Rect bounds(layer->visibleBounds());
+
+        // handle hidden surfaces by setting the visible region to empty
+        Region opaqueRegion;
+        Region visibleRegion;
+        Region coveredRegion;
+        if (UNLIKELY((s.flags & ISurfaceComposer::eLayerHidden) || !s.alpha)) {
+            visibleRegion.clear();
+        } else {
+            const bool translucent = layer->needsBlending();
+            visibleRegion.set(bounds);
+            coveredRegion = visibleRegion;
+
+            // Remove the transparent area from the visible region
+            if (translucent) {
+                visibleRegion.subtractSelf(layer->transparentRegionScreen);
+            }
+
+            // compute the opaque region
+            if (s.alpha==255 && !translucent && layer->getOrientation()>=0) {
+                // the opaque region is the visible region
+                opaqueRegion = visibleRegion;
+            }
+        }
+
+        // subtract the opaque region covered by the layers above us
+        visibleRegion.subtractSelf(aboveOpaqueLayers);
+        coveredRegion.andSelf(aboveCoveredLayers);
+
+        // compute this layer's dirty region
+        if (layer->contentDirty) {
+            // we need to invalidate the whole region
+            dirty = visibleRegion;
+            // as well, as the old visible region
+            dirty.orSelf(layer->visibleRegionScreen);
+            layer->contentDirty = false;
+        } else {
+            // compute the exposed region
+            // dirty = what's visible now - what's wasn't covered before
+            //       = what's visible now & what's was covered before
+            dirty = visibleRegion.intersect(layer->coveredRegionScreen);            
+        }
+        dirty.subtractSelf(aboveOpaqueLayers);
+
+        // accumulate to the screen dirty region
+        dirtyRegion.orSelf(dirty);
+
+        // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
+        aboveOpaqueLayers.orSelf(opaqueRegion);
+        aboveCoveredLayers.orSelf(bounds);
+        
+        // Store the visible region is screen space
+        layer->setVisibleRegion(visibleRegion);
+        layer->setCoveredRegion(coveredRegion);
+
+        // If a secure layer is partially visible, lockdown the screen!
+        if (layer->isSecure() && !visibleRegion.isEmpty()) {
+            secureFrameBuffer = true;
+        }
+    }
+
+    mSecureFrameBuffer = secureFrameBuffer;
+    opaqueRegion = aboveOpaqueLayers;
+}
+
+
+void SurfaceFlinger::commitTransaction()
+{
+    mDrawingState = mCurrentState;
+    mTransactionCV.signal();
+}
+
+void SurfaceFlinger::handlePageFlip()
+{
+    bool visibleRegions = mVisibleRegionsDirty;
+    LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
+    visibleRegions |= lockPageFlip(currentLayers);
+
+        const DisplayHardware& hw = graphicPlane(0).displayHardware();
+        const Region screenRegion(hw.bounds());
+        if (visibleRegions) {
+            Region opaqueRegion;
+            computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
+            mWormholeRegion = screenRegion.subtract(opaqueRegion);
+            mVisibleRegionsDirty = false;
+        }
+
+    unlockPageFlip(currentLayers);
+    mDirtyRegion.andSelf(screenRegion);
+}
+
+bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
+{
+    bool recomputeVisibleRegions = false;
+    size_t count = currentLayers.size();
+    LayerBase* const* layers = currentLayers.array();
+    for (size_t i=0 ; i<count ; i++) {
+        LayerBase* const layer = layers[i];
+        layer->lockPageFlip(recomputeVisibleRegions);
+    }
+    return recomputeVisibleRegions;
+}
+
+void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
+{
+    const GraphicPlane& plane(graphicPlane(0));
+    const Transform& planeTransform(plane.transform());
+    size_t count = currentLayers.size();
+    LayerBase* const* layers = currentLayers.array();
+    for (size_t i=0 ; i<count ; i++) {
+        LayerBase* const layer = layers[i];
+        layer->unlockPageFlip(planeTransform, mDirtyRegion);
+    }
+}
+
+void SurfaceFlinger::handleRepaint()
+{
+    // set the frame buffer
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+
+    if (UNLIKELY(mDebugRegion)) {
+        debugFlashRegions();
+    }
+
+    // compute the invalid region
+    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.
+    } else {
+        if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
+            // we need to fully redraw the part that will be updated
+            mDirtyRegion.set(mInvalidRegion.bounds());
+        } else {
+            // we need to redraw everything
+            mDirtyRegion.set(hw.bounds());
+            mInvalidRegion = mDirtyRegion;
+        }
+    }
+
+    // compose all surfaces
+    composeSurfaces(mDirtyRegion);
+
+    // clear the dirty regions
+    mDirtyRegion.clear();
+}
+
+void SurfaceFlinger::composeSurfaces(const Region& dirty)
+{
+    if (UNLIKELY(!mWormholeRegion.isEmpty())) {
+        // should never happen unless the window manager has a bug
+        // draw something...
+        drawWormhole();
+    }
+    const SurfaceFlinger& flinger(*this);
+    const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
+    const size_t count = drawingLayers.size();
+    LayerBase const* const* const layers = drawingLayers.array();
+    for (size_t i=0 ; i<count ; ++i) {
+        LayerBase const * const layer = layers[i];
+        const Region& visibleRegion(layer->visibleRegionScreen);
+        if (!visibleRegion.isEmpty())  {
+            const Region clip(dirty.intersect(visibleRegion));
+            if (!clip.isEmpty()) {
+                layer->draw(clip);
+            }
+        }
+    }
+}
+
+void SurfaceFlinger::unlockClients()
+{
+    const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
+    const size_t count = drawingLayers.size();
+    LayerBase* const* const layers = drawingLayers.array();
+    for (size_t i=0 ; i<count ; ++i) {
+        LayerBase* const layer = layers[i];
+        layer->finishPageFlip();
+    }
+}
+
+void SurfaceFlinger::scheduleBroadcast(Client* client)
+{
+    if (mLastScheduledBroadcast != client) {
+        mLastScheduledBroadcast = client;
+        mScheduledBroadcasts.add(client);
+    }
+}
+
+void SurfaceFlinger::executeScheduledBroadcasts()
+{
+    SortedVector<Client*>& list = mScheduledBroadcasts;
+    size_t count = list.size();
+    while (count--) {
+        per_client_cblk_t* const cblk = list[count]->ctrlblk;
+        if (cblk->lock.tryLock() == NO_ERROR) {
+            cblk->cv.broadcast();
+            list.removeAt(count);
+            cblk->lock.unlock();
+        } else {
+            // schedule another round
+            LOGW("executeScheduledBroadcasts() skipped, "
+                "contention on the client. We'll try again later...");
+            signalDelayedEvent(ms2ns(4));
+        }
+    }
+    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()));
+    }
+
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_BLEND);
+    glDisable(GL_DITHER);
+    glDisable(GL_SCISSOR_TEST);
+
+    glColor4x(0x10000, 0, 0x10000, 0x10000);
+
+    Rect r;
+    Region::iterator iterator(mDirtyRegion);
+    while (iterator.iterate(&r)) {
+        GLfloat vertices[][2] = {
+                { r.left,  r.top },
+                { r.left,  r.bottom },
+                { r.right, r.bottom },
+                { r.right, r.top }
+        };
+        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();
+
+    if (mDebugRegion > 1)
+       usleep(mDebugRegion * 1000);
+
+    glEnable(GL_SCISSOR_TEST);
+    //mDirtyRegion.dump("mDirtyRegion");
+}
+
+void SurfaceFlinger::drawWormhole() const
+{
+    const Region region(mWormholeRegion.intersect(mDirtyRegion));
+    if (region.isEmpty())
+        return;
+
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const int32_t width = hw.getWidth();
+    const int32_t height = hw.getHeight();
+
+    glDisable(GL_BLEND);
+    glDisable(GL_DITHER);
+
+    if (LIKELY(!mDebugBackground)) {
+        glClearColorx(0,0,0,0);
+        Rect r;
+        Region::iterator iterator(region);
+        while (iterator.iterate(&r)) {
+            const GLint sy = height - (r.top + r.height());
+            glScissor(r.left, sy, r.width(), r.height());
+            glClear(GL_COLOR_BUFFER_BIT);
+        }
+    } else {
+        const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
+                { width, height }, { 0, height }  };
+        const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 },  { 1, 1 }, { 0, 1 } };
+        glVertexPointer(2, GL_SHORT, 0, vertices);
+        glTexCoordPointer(2, GL_SHORT, 0, tcoords);
+        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+        glEnable(GL_TEXTURE_2D);
+        glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        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)) {
+            const GLint sy = height - (r.top + r.height());
+            glScissor(r.left, sy, r.width(), r.height());
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        }
+        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    }
+}
+
+void SurfaceFlinger::debugShowFPS() const
+{
+    static int mFrameCount;
+    static int mLastFrameCount = 0;
+    static nsecs_t mLastFpsTime = 0;
+    static float mFps = 0;
+    mFrameCount++;
+    nsecs_t now = systemTime();
+    nsecs_t diff = now - mLastFpsTime;
+    if (diff > ms2ns(250)) {
+        mFps =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
+        mLastFpsTime = now;
+        mLastFrameCount = mFrameCount;
+    }
+    // XXX: mFPS has the value we want
+ }
+
+status_t SurfaceFlinger::addLayer(LayerBase* layer)
+{
+    Mutex::Autolock _l(mStateLock);
+    addLayer_l(layer);
+    setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::removeLayer(LayerBase* layer)
+{
+    Mutex::Autolock _l(mStateLock);
+    removeLayer_l(layer);
+    setTransactionFlags(eTransactionNeeded);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer)
+{
+    layer->forceVisibilityTransaction();
+    setTransactionFlags(eTraversalNeeded);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::addLayer_l(LayerBase* layer)
+{
+    ssize_t i = mCurrentState.layersSortedByZ.add(
+                layer, &LayerBase::compareCurrentStateZ);
+    LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer);
+    if (lbc) {
+        mLayerMap.add(lbc->serverIndex(), lbc);
+    }
+    mRemovedLayers.remove(layer);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase)
+{
+    ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
+    if (index >= 0) {
+        mRemovedLayers.add(layerBase);
+        LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase);
+        if (layer) {
+            mLayerMap.removeItem(layer->serverIndex());
+        }
+        return NO_ERROR;
+    }
+    // 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;
+}
+
+void SurfaceFlinger::free_resources_l()
+{
+    // Destroy layers that were removed
+    destroy_all_removed_layers_l();
+
+    // free resources associated with disconnected clients
+    SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
+    Vector<Client*>& disconnectedClients(mDisconnectedClients);
+    const size_t count = disconnectedClients.size();
+    for (size_t i=0 ; i<count ; i++) {
+        Client* client = disconnectedClients[i];
+        // if this client is the scheduled broadcast list,
+        // remove it from there (and we don't need to signal it
+        // since it is dead).
+        int32_t index = scheduledBroadcasts.indexOf(client);
+        if (index >= 0) {
+            scheduledBroadcasts.removeItemsAt(index);
+        }
+        mTokens.release(client->cid);
+        delete client;
+    }
+    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;
+}
+
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
+{
+    uint32_t old = android_atomic_or(flags, &mTransactionFlags);
+    if ((old & flags)==0) { // wake the server up
+        if (delay > 0) {
+            signalDelayedEvent(delay);
+        } else {
+            signalEvent();
+        }
+    }
+    return old;
+}
+
+void SurfaceFlinger::openGlobalTransaction()
+{
+    android_atomic_inc(&mTransactionCount);
+}
+
+void SurfaceFlinger::closeGlobalTransaction()
+{
+    if (android_atomic_dec(&mTransactionCount) == 1) {
+        signalEvent();
+    }
+}
+
+status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
+{
+    if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
+        return BAD_VALUE;
+
+    Mutex::Autolock _l(mStateLock);
+    mCurrentState.freezeDisplay = 1;
+    setTransactionFlags(eTransactionNeeded);
+
+    // flags is intended to communicate some sort of animation behavior
+    // (for instance fadding)
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
+{
+    if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
+        return BAD_VALUE;
+
+    Mutex::Autolock _l(mStateLock);
+    mCurrentState.freezeDisplay = 0;
+    setTransactionFlags(eTransactionNeeded);
+
+    // flags is intended to communicate some sort of animation behavior
+    // (for instance fadding)
+    return NO_ERROR;
+}
+
+int SurfaceFlinger::setOrientation(DisplayID dpy, int orientation)
+{
+    if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
+        return BAD_VALUE;
+
+    Mutex::Autolock _l(mStateLock);
+    if (mCurrentState.orientation != orientation) {
+        if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
+            mCurrentState.orientation = orientation;
+            setTransactionFlags(eTransactionNeeded);
+            mTransactionCV.wait(mStateLock);
+        } else {
+            orientation = BAD_VALUE;
+        }
+    }
+    return orientation;
+}
+
+sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
+        ISurfaceFlingerClient::surface_data_t* params,
+        DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
+        uint32_t flags)
+{
+    LayerBaseClient* layer = 0;
+    sp<LayerBaseClient::Surface> surfaceHandle;
+    Mutex::Autolock _l(mStateLock);
+    Client* const c = mClientsMap.valueFor(clientId);
+    if (UNLIKELY(!c)) {
+        LOGE("createSurface() failed, client not found (id=%d)", clientId);
+        return surfaceHandle;
+    }
+
+    //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
+    int32_t id = c->generateId(pid);
+    if (uint32_t(id) >= NUM_LAYERS_MAX) {
+        LOGE("createSurface() failed, generateId = %d", id);
+        return surfaceHandle;
+    }
+
+    switch (flags & eFXSurfaceMask) {
+        case eFXSurfaceNormal:
+            if (UNLIKELY(flags & ePushBuffers)) {
+                layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags);
+            } else {
+                layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);
+            }
+            break;
+        case eFXSurfaceBlur:
+            layer = createBlurSurfaceLocked(c, d, id, w, h, flags);
+            break;
+        case eFXSurfaceDim:
+            layer = createDimSurfaceLocked(c, d, id, w, h, flags);
+            break;
+    }
+
+    if (layer) {
+        setTransactionFlags(eTransactionNeeded);
+        surfaceHandle = layer->getSurface();
+        if (surfaceHandle != 0)
+            surfaceHandle->getSurfaceData(params);
+    }
+
+    return surfaceHandle;
+}
+
+LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
+        Client* client, DisplayID display,
+        int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+{
+    // initialize the surfaces
+    switch (format) { // TODO: take h/w into account
+    case PIXEL_FORMAT_TRANSPARENT:
+    case PIXEL_FORMAT_TRANSLUCENT:
+        format = PIXEL_FORMAT_RGBA_8888;
+        break;
+    case PIXEL_FORMAT_OPAQUE:
+        format = PIXEL_FORMAT_RGB_565;
+        break;
+    }
+
+    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;
+    }
+    return layer;
+}
+
+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);
+    layer->initStates(w, h, flags);
+    addLayer_l(layer);
+    return layer;
+}
+
+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);
+    layer->initStates(w, h, flags);
+    addLayer_l(layer);
+    return layer;
+}
+
+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);
+    layer->initStates(w, h, flags);
+    addLayer_l(layer);
+    return layer;
+}
+
+status_t SurfaceFlinger::destroySurface(SurfaceID index)
+{
+    Mutex::Autolock _l(mStateLock);
+    LayerBaseClient* const layer = getLayerUser_l(index);
+    status_t err = removeLayer_l(layer);
+    if (err < 0)
+        return err;
+    setTransactionFlags(eTransactionNeeded);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::setClientState(
+        ClientID cid,
+        int32_t count,
+        const layer_state_t* states)
+{
+    Mutex::Autolock _l(mStateLock);
+    uint32_t flags = 0;
+    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) {
+            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;
+            }
+            if (what & eLayerChanged) {
+                if (layer->setLayer(s.z)) {
+                    mCurrentState.layersSortedByZ.reorder(
+                            layer, &Layer::compareCurrentStateZ);
+                    // we need traversal (state changed)
+                    // AND transaction (list changed)
+                    flags |= eTransactionNeeded|eTraversalNeeded;
+                }
+            }
+            if (what & eSizeChanged) {
+                if (layer->setSize(s.w, s.h))
+                    flags |= eTraversalNeeded;
+            }
+            if (what & eAlphaChanged) {
+                if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+                    flags |= eTraversalNeeded;
+            }
+            if (what & eMatrixChanged) {
+                if (layer->setMatrix(s.matrix))
+                    flags |= eTraversalNeeded;
+            }
+            if (what & eTransparentRegionChanged) {
+                if (layer->setTransparentRegionHint(s.transparentRegion))
+                    flags |= eTraversalNeeded;
+            }
+            if (what & eVisibilityChanged) {
+                if (layer->setFlags(s.flags, s.mask))
+                    flags |= eTraversalNeeded;
+            }
+        }
+    }
+    if (flags) {
+        setTransactionFlags(flags);
+    }
+    return NO_ERROR;
+}
+
+LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const
+{
+    return mLayerMap.valueFor(s);
+}
+
+void SurfaceFlinger::screenReleased(int dpy)
+{
+    // this may be called by a signal handler, we can't do too much in here
+    android_atomic_or(eConsoleReleased, &mConsoleSignals);
+    signalEvent();
+}
+
+void SurfaceFlinger::screenAcquired(int dpy)
+{
+    // this may be called by a signal handler, we can't do too much in here
+    android_atomic_or(eConsoleAcquired, &mConsoleSignals);
+    signalEvent();
+}
+
+status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 1024;
+    char buffer[SIZE];
+    String8 result;
+    if (checkCallingPermission(
+            String16("android.permission.DUMP")) == false)
+    { // not allowed
+        snprintf(buffer, SIZE, "Permission Denial: "
+                "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
+                IPCThreadState::self()->getCallingPid(),
+                IPCThreadState::self()->getCallingUid());
+        result.append(buffer);
+    } else {
+        Mutex::Autolock _l(mStateLock);
+        size_t s = mClientsMap.size();
+        char name[64];
+        for (size_t i=0 ; i<s ; i++) {
+            Client* client = mClientsMap.valueAt(i);
+            sprintf(name, "  Client (id=0x%08x)", client->cid);
+            client->dump(name);
+        }
+        const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+        const size_t count = currentLayers.size();
+        for (size_t i=0 ; i<count ; i++) {
+            /*** LayerBase ***/
+            LayerBase const * const layer = currentLayers[i];
+            const Layer::State& s = layer->drawingState();
+            snprintf(buffer, SIZE,
+                    "+ %s %p\n"
+                    "      "
+                    "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,
+                    s.z, layer->tx(), layer->ty(), s.w, s.h,
+                    layer->needsBlending(), layer->contentDirty,
+                    s.alpha, s.flags,
+                    s.transform[0], s.transform[1],
+                    s.transform[2], s.transform[3]);
+            result.append(buffer);
+            buffer[0] = 0;
+            /*** LayerBaseClient ***/
+            LayerBaseClient* const lbc =
+                LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer);
+            if (lbc) {
+                snprintf(buffer, SIZE,
+                        "      "
+                        "id=0x%08x, client=0x%08x, identity=%u\n",
+                        lbc->clientIndex(), lbc->client ? lbc->client->cid : 0,
+                        lbc->getIdentity());
+            }
+            result.append(buffer);
+            buffer[0] = 0;
+            /*** Layer ***/
+            Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer);
+            if (l) {
+                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,"
+                        " 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(),
+                        l->lcblk->swapState);
+            }
+            result.append(buffer);
+            buffer[0] = 0;
+            s.transparentRegion.dump(result, "transparentRegion");
+            layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
+            layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
+        }
+        mWormholeRegion.dump(result, "WormholeRegion");
+        const DisplayHardware& hw(graphicPlane(0).displayHardware());
+        snprintf(buffer, SIZE,
+                "  display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
+                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");
+        }
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case CREATE_CONNECTION:
+        case OPEN_GLOBAL_TRANSACTION:
+        case CLOSE_GLOBAL_TRANSACTION:
+        case SET_ORIENTATION:
+        case FREEZE_DISPLAY:
+        case UNFREEZE_DISPLAY:
+        case BOOT_FINISHED:
+        case REVOKE_GPU:
+        {
+            // codes that require permission check
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int self_pid = getpid();
+            if (UNLIKELY(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;
+                }
+            }
+        }
+    }
+
+    status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
+    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
+        // HARDWARE_TEST stuff...
+        if (UNLIKELY(checkCallingPermission(
+                String16("android.permission.HARDWARE_TEST")) == false))
+        { // not allowed
+            LOGE("Permission Denial: pid=%d, uid=%d\n",
+                    IPCThreadState::self()->getCallingPid(),
+                    IPCThreadState::self()->getCallingUid());
+            return PERMISSION_DENIED;
+        }
+        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();
+                    }
+                }
+                return NO_ERROR;
+            case 1001:  // SHOW_FPS
+                n = data.readInt32();
+                mDebugFps = n ? 1 : 0;
+                return NO_ERROR;
+            case 1002:  // SHOW_UPDATES
+                n = data.readInt32();
+                mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
+                return NO_ERROR;
+            case 1003:  // SHOW_BACKGROUND
+                n = data.readInt32();
+                mDebugBackground = n ? 1 : 0;
+                return NO_ERROR;
+            case 1004:{ // repaint everything
+                Mutex::Autolock _l(mStateLock);
+                const DisplayHardware& hw(graphicPlane(0).displayHardware());
+                mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
+                signalEvent();
+            }
+            return NO_ERROR;
+            case 1005: // ask GPU revoke
+                mGPU->friendlyRevoke();
+                return NO_ERROR;
+            case 1006: // revoke GPU
+                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(mDebugRegion);
+                reply->writeInt32(mDebugBackground);
+                return NO_ERROR;
+            case 1013: {
+                Mutex::Autolock _l(mStateLock);
+                const DisplayHardware& hw(graphicPlane(0).displayHardware());
+                reply->writeInt32(hw.getPageFlipCount());
+            }
+            return NO_ERROR;
+        }
+    }
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+#if 0
+#pragma mark -
+#endif
+
+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);
+    mCblkMemory = mCblkHeap->allocate(cblksize);
+    if (mCblkMemory != 0) {
+        ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer());
+        if (ctrlblk) { // construct the shared structure in-place.
+            new(ctrlblk) per_client_cblk_t;
+        }
+    }
+}
+
+Client::~Client() {
+    if (ctrlblk) {
+        const int pgsize = getpagesize();
+        ctrlblk->~per_client_cblk_t();  // destroy our shared-structure.
+    }
+}
+
+const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const {
+    return mFlinger->getSurfaceHeapManager();
+}
+
+int32_t Client::generateId(int pid)
+{
+    const uint32_t i = clz( ~mBitmap );
+    if (i >= NUM_LAYERS_MAX) {
+        return NO_MEMORY;
+    }
+    mPid = pid;
+    mInUse.add(uint8_t(i));
+    mBitmap |= 1<<(31-i);
+    return i;
+}
+status_t Client::bindLayer(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));
+    if (idx >= 0) {
+        mBitmap &= ~(1<<(31-id));
+        mLayers.removeItemsAt(idx);
+    }
+}
+
+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 {
+    ssize_t idx = mInUse.indexOf(uint8_t(i));
+    if (idx<0) return 0;
+    return mLayers[idx];
+}
+
+void Client::dump(const char* what)
+{
+}
+
+// ---------------------------------------------------------------------------
+#if 0
+#pragma mark -
+#endif
+
+BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk)
+    : mId(cid), mFlinger(flinger), mCblk(cblk)
+{
+}
+
+BClient::~BClient() {
+    // destroy all resources attached to this client
+    mFlinger->destroyConnection(mId);
+}
+
+void BClient::getControlBlocks(sp<IMemory>* ctrl) const {
+    *ctrl = mCblk;
+}
+
+sp<ISurface> BClient::createSurface(
+        ISurfaceFlingerClient::surface_data_t* params, int pid,
+        DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
+        uint32_t flags)
+{
+    return mFlinger->createSurface(mId, pid, params, display, w, h, format, flags);
+}
+
+status_t BClient::destroySurface(SurfaceID sid)
+{
+    sid |= (mId << 16); // add the client-part to id
+    return mFlinger->destroySurface(sid);
+}
+
+status_t BClient::setState(int32_t count, const layer_state_t* states)
+{
+    return mFlinger->setClientState(mId, count, states);
+}
+
+// ---------------------------------------------------------------------------
+
+GraphicPlane::GraphicPlane()
+    : mHw(0)
+{
+}
+
+GraphicPlane::~GraphicPlane() {
+    delete mHw;
+}
+
+bool GraphicPlane::initialized() const {
+    return mHw ? true : false;
+}
+
+void GraphicPlane::setDisplayHardware(DisplayHardware *hw) {
+    mHw = hw;
+}
+
+void GraphicPlane::setTransform(const Transform& tr) {
+    mTransform = tr;
+    mGlobalTransform = mOrientationTransform * mTransform;
+}
+
+status_t GraphicPlane::orientationToTransfrom(
+        int orientation, int w, int h, Transform* tr)
+{    
+    float a, b, c, d, x, y;
+    switch (orientation) {
+    case ISurfaceComposer::eOrientationDefault:
+        a=1; b=0; c=0; d=1; x=0; y=0;
+        break;
+    case ISurfaceComposer::eOrientation90:
+        a=0; b=-1; c=1; d=0; x=w; y=0;
+        break;
+    case ISurfaceComposer::eOrientation180:
+        a=-1; b=0; c=0; d=-1; x=w; y=h;
+        break;
+    case ISurfaceComposer::eOrientation270:
+        a=0; b=1; c=-1; d=0; x=0; y=h;
+        break;
+    default:
+        return BAD_VALUE;
+    }
+    tr->set(a, b, c, d);
+    tr->set(x, y);
+    return NO_ERROR;
+}
+
+status_t GraphicPlane::setOrientation(int orientation)
+{
+    const DisplayHardware& hw(displayHardware());
+    const float w = hw.getWidth();
+    const float h = hw.getHeight();
+
+    if (orientation == ISurfaceComposer::eOrientationDefault) {
+        // make sure the default orientation is optimal
+        mOrientationTransform.reset();
+        mGlobalTransform = mTransform;
+        return NO_ERROR;
+    }
+
+    // If the rotation can be handled in hardware, this is where
+    // the magic should happen.
+    if (UNLIKELY(orientation == 42)) {
+        float a, b, c, d, x, y;
+        const float r = (3.14159265f / 180.0f) * 42.0f;
+        const float si = sinf(r);
+        const float co = cosf(r);
+        a=co; b=-si; c=si; d=co;
+        x = si*(h*0.5f) + (1-co)*(w*0.5f);
+        y =-si*(w*0.5f) + (1-co)*(h*0.5f);
+        mOrientationTransform.set(a, b, c, d);
+        mOrientationTransform.set(x, y);
+    } else {
+        GraphicPlane::orientationToTransfrom(orientation, w, h,
+                &mOrientationTransform);
+    }
+    
+    mGlobalTransform = mOrientationTransform * mTransform;
+    return NO_ERROR;
+}
+
+const DisplayHardware& GraphicPlane::displayHardware() const {
+    return *mHw;
+}
+
+const Transform& GraphicPlane::transform() const {
+    return mGlobalTransform;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
new file mode 100644
index 0000000..f7d7764
--- /dev/null
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -0,0 +1,435 @@
+/*
+ * 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_SURFACE_FLINGER_H
+#define ANDROID_SURFACE_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/MemoryDealer.h>
+
+#include <ui/PixelFormat.h>
+#include <ui/ISurfaceComposer.h>
+#include <ui/ISurfaceFlingerClient.h>
+
+#include <private/ui/SharedState.h>
+#include <private/ui/LayerState.h>
+#include <private/ui/SurfaceFlingerSynchro.h>
+
+#include "Barrier.h"
+#include "BootAnimation.h"
+#include "CPUGauge.h"
+#include "Layer.h"
+#include "Tokenizer.h"
+
+struct copybit_device_t;
+struct overlay_device_t;
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class Client;
+class BClient;
+class DisplayHardware;
+class FreezeLock;
+class GPUHardwareInterface;
+class IGPUCallback;
+class Layer;
+class LayerBuffer;
+class LayerOrientationAnim;
+class OrientationAnimation;
+class SurfaceHeapManager;
+
+typedef int32_t ClientID;
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// ---------------------------------------------------------------------------
+
+class Client
+{
+public:
+            Client(ClientID cid, const sp<SurfaceFlinger>& flinger);
+            ~Client();
+
+            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);
+
+    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; }
+    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;
+    ClientID                cid;
+
+    
+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;
+};
+
+// ---------------------------------------------------------------------------
+
+class GraphicPlane
+{
+public:
+    static status_t orientationToTransfrom(int orientation, int w, int h,
+            Transform* tr);
+
+                                GraphicPlane();
+                                ~GraphicPlane();
+
+        bool                    initialized() const;
+
+        void                    setDisplayHardware(DisplayHardware *);
+        void                    setTransform(const Transform& tr);
+        status_t                setOrientation(int orientation);
+
+        const DisplayHardware&  displayHardware() const;
+        const Transform&        transform() const;
+private:
+                                GraphicPlane(const GraphicPlane&);
+        GraphicPlane            operator = (const GraphicPlane&);
+
+        DisplayHardware*        mHw;
+        Transform               mTransform;
+        Transform               mOrientationTransform;
+        Transform               mGlobalTransform;
+};
+
+// ---------------------------------------------------------------------------
+
+enum {
+    eTransactionNeeded      = 0x01,
+    eTraversalNeeded        = 0x02
+};
+
+class SurfaceFlinger : public BnSurfaceComposer, protected Thread
+{
+public:
+    static void instantiate();
+    static void shutdown();
+
+                    SurfaceFlinger();
+    virtual         ~SurfaceFlinger();
+            void    init();
+
+    virtual status_t onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+
+    virtual status_t dump(int fd, const Vector<String16>& args);
+
+    // ISurfaceComposer interface
+    virtual sp<ISurfaceFlingerClient>   createConnection();
+    virtual sp<IMemory>                 getCblk() const;
+    virtual void                        bootFinished();
+    virtual void                        openGlobalTransaction();
+    virtual void                        closeGlobalTransaction();
+    virtual status_t                    freezeDisplay(DisplayID dpy, uint32_t flags);
+    virtual status_t                    unfreezeDisplay(DisplayID dpy, uint32_t flags);
+    virtual int                         setOrientation(DisplayID dpy, int orientation);
+    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);
+    
+private:
+    friend class BClient;
+    friend class LayerBase;
+    friend class LayerBuffer;
+    friend class LayerBaseClient;
+    friend class Layer;
+    friend class LayerBlur;
+
+    sp<ISurface> createSurface(ClientID client, int pid, 
+            ISurfaceFlingerClient::surface_data_t* params,
+            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);
+
+    LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display,
+            int32_t id, uint32_t w, uint32_t h, uint32_t flags);
+
+    LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display,
+            int32_t id, uint32_t w, uint32_t h, uint32_t flags);
+
+    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);
+
+
+    class LayerVector {
+    public:
+        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]; }
+    private:
+        KeyedVector<LayerBase*, size_t> lookup;
+        Vector<LayerBase*>              layers;
+    };
+
+    struct State {
+        State() {
+            orientation = ISurfaceComposer::eOrientationDefault;
+            freezeDisplay = 0;
+        }
+        LayerVector     layersSortedByZ;
+        uint8_t         orientation;
+        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();
+
+    const GraphicPlane&     graphicPlane(int dpy) const;
+          GraphicPlane&     graphicPlane(int dpy);
+
+            void        waitForEvent();
+            void        signalEvent();
+            void        signalDelayedEvent(nsecs_t delay);
+
+            void        handleConsoleEvents();
+            void        handleTransaction(uint32_t transactionFlags);
+
+            void        computeVisibleRegions(
+                            LayerVector& currentLayers,
+                            Region& dirtyRegion,
+                            Region& wormholeRegion);
+
+            void        handlePageFlip();
+            bool        lockPageFlip(const LayerVector& currentLayers);
+            void        unlockPageFlip(const LayerVector& currentLayers);
+            void        handleRepaint();
+            void        handleDebugCpu();
+            void        scheduleBroadcast(Client* client);
+            void        executeScheduledBroadcasts();
+            void        postFramebuffer();
+            void        composeSurfaces(const Region& dirty);
+            void        unlockClients();
+
+
+            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();
+            void        free_resources_l();
+
+            uint32_t    getTransactionFlags(uint32_t flags);
+            uint32_t    setTransactionFlags(uint32_t flags, nsecs_t delay = 0);
+            void        commitTransaction();
+
+
+            friend class FreezeLock;
+            sp<FreezeLock> getFreezeLock() const;
+            inline void incFreezeCount() { mFreezeCount++; }
+            inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; }
+            inline bool hasFreezeRequest() const { return mFreezeDisplay; }
+            inline bool isFrozen() const { 
+                return mFreezeDisplay || mFreezeCount>0;
+            }
+
+            
+            void        debugFlashRegions();
+            void        debugShowFPS() const;
+            void        drawWormhole() const;
+           
+                // access must be protected by mStateLock
+    mutable     Mutex                   mStateLock;
+                State                   mCurrentState;
+                State                   mDrawingState;
+    volatile    int32_t                 mTransactionFlags;
+    volatile    int32_t                 mTransactionCount;
+                Condition               mTransactionCV;
+
+                // protected by mStateLock (but we could use another lock)
+                Tokenizer                               mTokens;
+                DefaultKeyedVector<ClientID, Client*>   mClientsMap;
+                DefaultKeyedVector<SurfaceID, LayerBaseClient*>   mLayerMap;
+                GraphicPlane                            mGraphicPlanes[1];
+                SortedVector<LayerBase*>                mRemovedLayers;
+                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;
+                sp<BootAnimation>           mBootAnimation;
+                nsecs_t                     mBootTime;
+                
+                // Can only accessed from the main thread, these members
+                // don't need synchronization
+                Region                      mDirtyRegion;
+                Region                      mInvalidRegion;
+                Region                      mWormholeRegion;
+                Client*                     mLastScheduledBroadcast;
+                SortedVector<Client*>       mScheduledBroadcasts;
+                bool                        mVisibleRegionsDirty;
+                bool                        mDeferReleaseConsole;
+                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;
+                int                         mDebugNoBootAnimation;
+
+                // these are thread safe
+    mutable     Barrier                     mReadyToRunBarrier;
+    mutable     SurfaceFlingerSynchro       mSyncObject;
+    volatile    int32_t                     mDeplayedTransactionPending;
+
+                // atomic variables
+                enum {
+                    eConsoleReleased = 1,
+                    eConsoleAcquired = 2
+                };
+   volatile     int32_t                     mConsoleSignals;
+
+   // only written in the main thread, only read in other threads
+   volatile     int32_t                     mSecureFrameBuffer;
+};
+
+// ---------------------------------------------------------------------------
+
+class FreezeLock : public LightRefBase<FreezeLock> {
+    SurfaceFlinger* mFlinger;
+public:
+    FreezeLock(SurfaceFlinger* flinger)
+        : mFlinger(flinger) {
+        mFlinger->incFreezeCount();
+    }
+    ~FreezeLock() {
+        mFlinger->decFreezeCount();
+    }
+};
+
+// ---------------------------------------------------------------------------
+
+class BClient : public BnSurfaceFlingerClient
+{
+public:
+    BClient(SurfaceFlinger *flinger, ClientID cid,
+            const sp<IMemory>& cblk);
+    ~BClient();
+
+    // ISurfaceFlingerClient interface
+    virtual void getControlBlocks(sp<IMemory>* ctrl) const;
+
+    virtual sp<ISurface> createSurface(
+            surface_data_t* params, int pid,
+            DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
+            uint32_t flags);
+
+    virtual status_t destroySurface(SurfaceID surfaceId);
+    virtual status_t setState(int32_t count, const layer_state_t* states);
+
+private:
+    ClientID            mId;
+    SurfaceFlinger*     mFlinger;
+    sp<IMemory>         mCblk;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SURFACE_FLINGER_H
diff --git a/libs/surfaceflinger/Tokenizer.cpp b/libs/surfaceflinger/Tokenizer.cpp
new file mode 100644
index 0000000..ef51d6a
--- /dev/null
+++ b/libs/surfaceflinger/Tokenizer.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include "Tokenizer.h"
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+ANDROID_BASIC_TYPES_TRAITS(Tokenizer::run_t)
+
+Tokenizer::Tokenizer()
+{
+}
+
+Tokenizer::Tokenizer(const Tokenizer& other)
+    : mRanges(other.mRanges)
+{
+}
+
+Tokenizer::~Tokenizer()
+{
+}
+
+uint32_t Tokenizer::acquire()
+{
+    if (!mRanges.size() || mRanges[0].first) {
+        _insertTokenAt(0,0);
+        return 0;
+    }
+    
+    // just extend the first run
+    const run_t& run = mRanges[0];
+    uint32_t token = run.first + run.length;
+    _insertTokenAt(token, 1);
+    return token;
+}
+
+bool Tokenizer::isAcquired(uint32_t token) const
+{
+    return (_indexOrderOf(token) >= 0);
+}
+
+status_t Tokenizer::reserve(uint32_t token)
+{
+    size_t o;
+    const ssize_t i = _indexOrderOf(token, &o);
+    if (i >= 0) {
+        return BAD_VALUE; // this token is already taken
+    }
+    ssize_t err = _insertTokenAt(token, o);
+    return (err<0) ? err : status_t(NO_ERROR);
+}
+
+status_t Tokenizer::release(uint32_t token)
+{
+    const ssize_t i = _indexOrderOf(token);
+    if (i >= 0) {
+        const run_t& run = mRanges[i];
+        if ((token >= run.first) && (token < run.first+run.length)) {
+            // token in this range, we need to split
+            run_t& run = mRanges.editItemAt(i);
+            if ((token == run.first) || (token == run.first+run.length-1)) {
+                if (token == run.first) {
+                    run.first += 1;
+                }
+                run.length -= 1;
+                if (run.length == 0) {
+                    // XXX: should we systematically remove a run that's empty?
+                    mRanges.removeItemsAt(i);
+                }
+            } else {
+                // split the run
+                run_t new_run;
+                new_run.first = token+1;
+                new_run.length = run.first+run.length - new_run.first;
+                run.length = token - run.first;
+                mRanges.insertAt(new_run, i+1);
+            }
+            return NO_ERROR;
+        }
+    }
+    return NAME_NOT_FOUND;
+}
+
+ssize_t Tokenizer::_indexOrderOf(uint32_t token, size_t* order) const
+{
+    // binary search
+    ssize_t err = NAME_NOT_FOUND;
+    ssize_t l = 0;
+    ssize_t h = mRanges.size()-1;
+    ssize_t mid;
+    const run_t* a = mRanges.array();
+    while (l <= h) {
+        mid = l + (h - l)/2;
+        const run_t* const curr = a + mid;
+        int c = 0;
+        if (token < curr->first)                        c = 1;
+        else if (token >= curr->first+curr->length)     c = -1;
+        if (c == 0) {
+            err = l = mid;
+            break;
+        } else if (c < 0) {
+            l = mid + 1;
+        } else {
+            h = mid - 1;
+        }
+    }
+    if (order) *order = l;
+    return err;
+}
+
+ssize_t Tokenizer::_insertTokenAt(uint32_t token, size_t index)
+{
+    const size_t c = mRanges.size();
+
+    if (index >= 1) {
+        // do we need to merge with the previous run?
+        run_t& p = mRanges.editItemAt(index-1);
+        if (p.first+p.length == token) {
+            p.length += 1;
+            if (index < c) {
+                const run_t& n = mRanges[index];
+                if (token+1 == n.first) {
+                    p.length += n.length;
+                    mRanges.removeItemsAt(index);
+                }
+            }
+            return index;
+        }
+    }
+    
+    if (index < c) {
+        // do we need to merge with the next run?
+        run_t& n = mRanges.editItemAt(index);
+        if (token+1 == n.first) {
+            n.first -= 1;
+            n.length += 1;
+            return index;
+        }
+    }
+
+    return mRanges.insertAt(run_t(token,1), index);
+}
+
+void Tokenizer::dump() const
+{
+    const run_t* ranges = mRanges.array();
+    const size_t c = mRanges.size();
+    printf("Tokenizer (%p, size = %lu)\n", this, c);
+    for (size_t i=0 ; i<c ; i++) {
+        printf("%lu: (%u, %u)\n", i, ranges[i].first, ranges[i].length);
+    }
+}
+
+}; // namespace android
+
diff --git a/libs/surfaceflinger/Tokenizer.h b/libs/surfaceflinger/Tokenizer.h
new file mode 100644
index 0000000..6b3057d
--- /dev/null
+++ b/libs/surfaceflinger/Tokenizer.h
@@ -0,0 +1,57 @@
+/*
+ * 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_TOKENIZER_H
+#define ANDROID_TOKENIZER_H
+
+#include <utils/Vector.h>
+#include <utils/Errors.h>
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+class Tokenizer
+{
+public:
+                Tokenizer();
+                Tokenizer(const Tokenizer& other);
+                ~Tokenizer();
+
+    uint32_t    acquire();
+    status_t    reserve(uint32_t token);
+    status_t    release(uint32_t token);
+    bool        isAcquired(uint32_t token) const;
+
+    void dump() const;
+
+    struct run_t {
+        run_t() {};
+        run_t(uint32_t f, uint32_t l) : first(f), length(l) {}
+        uint32_t    first;
+        uint32_t    length;
+    };
+private:
+    ssize_t _indexOrderOf(uint32_t token, size_t* order=0) const;
+    ssize_t _insertTokenAt(uint32_t token, size_t index);
+    Vector<run_t>   mRanges;
+};
+
+}; // namespace android
+
+// ----------------------------------------------------------------------------
+
+#endif // ANDROID_TOKENIZER_H
diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp
new file mode 100644
index 0000000..bec7a64
--- /dev/null
+++ b/libs/surfaceflinger/Transform.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/Region.h>
+
+#include <private/pixelflinger/ggl_fixed.h>
+
+#include "Transform.h"
+
+// ---------------------------------------------------------------------------
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+Transform::Transform()
+    : mType(0)
+{
+    mTransform.reset();
+}
+
+Transform::Transform(const Transform&  other)
+    : mTransform(other.mTransform), mType(other.mType)
+{
+}
+
+Transform::~Transform() {
+}
+
+Transform Transform::operator * (const Transform& rhs) const
+{
+    if (LIKELY(mType == 0))
+        return rhs;
+
+    Transform r(*this);
+    r.mTransform.preConcat(rhs.mTransform);
+    r.mType |= rhs.mType;
+    return r;
+}
+
+float Transform::operator [] (int i) const
+{
+    float r = 0;
+    switch(i) {
+        case 0: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleX] );  break;
+        case 1: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewX] );   break;
+        case 2: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewY] );   break;
+        case 3: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleY] );  break;
+    }
+    return r;
+}
+
+uint8_t Transform::type() const
+{
+    if (UNLIKELY(mType & 0x80000000)) {
+        mType = mTransform.getType();
+    }
+    return uint8_t(mType & 0xFF);
+}
+
+bool Transform::transformed() const {
+    return type() > SkMatrix::kTranslate_Mask;
+}
+
+int Transform::tx() const {
+    return SkScalarRound( mTransform[SkMatrix::kMTransX] );
+}
+
+int Transform::ty() const {
+    return SkScalarRound( mTransform[SkMatrix::kMTransY] );
+}
+
+void Transform::reset() {
+    mTransform.reset();
+    mType = 0;
+}
+
+void Transform::set( float xx, float xy,
+                     float yx, float yy)
+{
+    mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(xx));
+    mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(xy));
+    mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(yx));
+    mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(yy));
+    mType |= 0x80000000;
+}
+
+void Transform::set(int tx, int ty)
+{
+    if (tx | ty) {
+        mTransform.set(SkMatrix::kMTransX, SkIntToScalar(tx));
+        mTransform.set(SkMatrix::kMTransY, SkIntToScalar(ty));
+        mType |= SkMatrix::kTranslate_Mask;
+    } else {
+        mTransform.set(SkMatrix::kMTransX, 0);
+        mTransform.set(SkMatrix::kMTransY, 0);
+        mType &= ~SkMatrix::kTranslate_Mask;
+    }
+}
+
+void Transform::transform(GLfixed* point, int x, int y) const
+{
+    SkPoint s;
+    mTransform.mapXY(SkIntToScalar(x), SkIntToScalar(y), &s);
+    point[0] = SkScalarToFixed(s.fX);
+    point[1] = SkScalarToFixed(s.fY);
+}
+
+Rect Transform::makeBounds(int w, int h) const
+{
+    Rect r;
+    SkRect d, s;
+    s.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
+    mTransform.mapRect(&d, s);
+    r.left   = SkScalarRound( d.fLeft );
+    r.top    = SkScalarRound( d.fTop );
+    r.right  = SkScalarRound( d.fRight );
+    r.bottom = SkScalarRound( d.fBottom );
+    return r;
+}
+
+Rect Transform::transform(const Rect& bounds) const
+{
+    Rect r;
+    SkRect d, s;
+    s.set(  SkIntToScalar( bounds.left ),
+            SkIntToScalar( bounds.top ),
+            SkIntToScalar( bounds.right ),
+            SkIntToScalar( bounds.bottom ));
+    mTransform.mapRect(&d, s);
+    r.left   = SkScalarRound( d.fLeft );
+    r.top    = SkScalarRound( d.fTop );
+    r.right  = SkScalarRound( d.fRight );
+    r.bottom = SkScalarRound( d.fBottom );
+    return r;
+}
+
+Region Transform::transform(const Region& reg) const
+{
+    Region out;
+    if (UNLIKELY(transformed())) {
+        if (LIKELY(preserveRects())) {
+            Rect r;
+            Region::iterator iterator(reg);
+            while (iterator.iterate(&r)) {
+                out.orSelf(transform(r));
+            }
+        } else {
+            out.set(transform(reg.bounds()));
+        }
+    } else {
+        out = reg.translate(tx(), ty());
+    }
+    return out;
+}
+
+int32_t Transform::getOrientation() const
+{
+    uint32_t flags = 0;
+    if (UNLIKELY(transformed())) {
+        SkScalar a = mTransform[SkMatrix::kMScaleX];
+        SkScalar b = mTransform[SkMatrix::kMSkewX];
+        SkScalar c = mTransform[SkMatrix::kMSkewY];
+        SkScalar d = mTransform[SkMatrix::kMScaleY];
+        if (b==0 && c==0 && a && d) {
+            if (a<0)    flags |= FLIP_H;
+            if (d<0)    flags |= FLIP_V;
+        } else if (b && c && a==0 && d==0) {
+            flags |= ROT_90;
+            if (b>0)    flags |= FLIP_H;
+            if (c<0)    flags |= FLIP_V;
+        } else {
+            flags = 0x80000000;
+        }
+    }
+    return flags;
+}
+
+bool Transform::preserveRects() const
+{
+    return mTransform.rectStaysRect();
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h
new file mode 100644
index 0000000..0b4835e
--- /dev/null
+++ b/libs/surfaceflinger/Transform.h
@@ -0,0 +1,87 @@
+/*
+ * 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_TRANSFORM_H
+#define ANDROID_TRANSFORM_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <ui/Point.h>
+#include <ui/Rect.h>
+
+#include <GLES/gl.h>
+
+#include <core/SkMatrix.h>
+
+namespace android {
+
+class Region;
+
+// ---------------------------------------------------------------------------
+
+class Transform
+{
+public:
+                    Transform();
+                    Transform(const Transform&  other);
+                    ~Transform();
+
+            enum orientation_flags {
+                ROT_0   = 0x00000000,
+                FLIP_H  = 0x00000001,
+                FLIP_V  = 0x00000002,
+                ROT_90  = 0x00000004,
+                ROT_180 = FLIP_H|FLIP_V,
+                ROT_270 = ROT_180|ROT_90,
+                ROT_INVALID = 0x80000000
+            };
+
+            bool    transformed() const;
+            int32_t getOrientation() const;
+            bool    preserveRects() const;
+            
+            int     tx() const;
+            int     ty() const;
+        
+            void    reset();
+            void    set(float xx, float xy, float yx, float yy);
+            void    set(int tx, int ty);
+
+            Rect    makeBounds(int w, int h) const;
+            void    transform(GLfixed* point, int x, int y) const;
+            Region  transform(const Region& reg) const;
+            Rect    transform(const Rect& bounds) const;
+
+            Transform operator * (const Transform& rhs) const;
+            float operator [] (int i) const;
+
+    inline uint32_t getType() const { return type(); }
+            
+    inline Transform(bool) : mType(0xFF) { };
+
+private:
+    uint8_t     type() const;
+
+private:
+            SkMatrix    mTransform;
+    mutable uint32_t    mType;      
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* ANDROID_TRANSFORM_H */
diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp
new file mode 100644
index 0000000..0ccd71f
--- /dev/null
+++ b/libs/surfaceflinger/VRamHeap.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "SurfaceFlinger"
+
+#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/VRamHeap.h b/libs/surfaceflinger/VRamHeap.h
new file mode 100644
index 0000000..9140167
--- /dev/null
+++ b/libs/surfaceflinger/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/clz.cpp b/libs/surfaceflinger/clz.cpp
new file mode 100644
index 0000000..2456b86
--- /dev/null
+++ b/libs/surfaceflinger/clz.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "clz.h"
+
+namespace android {
+
+int clz_impl(int32_t x)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    return __builtin_clz(x);
+#else
+    if (!x) return 32;
+    int e = 31;
+    if (x&0xFFFF0000)   { e -=16; x >>=16; }
+    if (x&0x0000FF00)   { e -= 8; x >>= 8; }
+    if (x&0x000000F0)   { e -= 4; x >>= 4; }
+    if (x&0x0000000C)   { e -= 2; x >>= 2; }
+    if (x&0x00000002)   { e -= 1; }
+    return e;
+#endif
+}
+
+}; // namespace android
diff --git a/libs/surfaceflinger/clz.h b/libs/surfaceflinger/clz.h
new file mode 100644
index 0000000..0ddf986
--- /dev/null
+++ b/libs/surfaceflinger/clz.h
@@ -0,0 +1,37 @@
+/*
+ * 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_SURFACE_FLINGER_CLZ_H
+
+#include <stdint.h>
+
+namespace android {
+
+int clz_impl(int32_t x);
+
+int inline clz(int32_t x)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    return __builtin_clz(x);
+#else
+    return clz_impl(x);
+#endif
+}
+
+
+}; // namespace android
+
+#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */
diff --git a/libs/surfaceflinger/tests/Android.mk b/libs/surfaceflinger/tests/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/libs/surfaceflinger/tests/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/libs/surfaceflinger/tests/overlays/Android.mk b/libs/surfaceflinger/tests/overlays/Android.mk
new file mode 100644
index 0000000..dc47e45
--- /dev/null
+++ b/libs/surfaceflinger/tests/overlays/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	overlays.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+    libui
+
+LOCAL_MODULE:= test-overlays
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/libs/surfaceflinger/tests/overlays/overlays.cpp b/libs/surfaceflinger/tests/overlays/overlays.cpp
new file mode 100644
index 0000000..f3c046f
--- /dev/null
+++ b/libs/surfaceflinger/tests/overlays/overlays.cpp
@@ -0,0 +1,58 @@
+#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, 320, 240, 
+            PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);
+
+    // get to the isurface
+    sp<ISurface> isurface = Test::getISurface(surface);
+    printf("isurface = %p\n", isurface.get());
+    
+    // now request an overlay
+    sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);
+    sp<Overlay> overlay = new Overlay(ref);
+    
+
+    /*
+     * here we can use the overlay API 
+     */
+    
+    overlay_buffer_t buffer; 
+    overlay->dequeueBuffer(&buffer);
+    printf("buffer = %p\n", buffer);
+    
+    void* address = overlay->getBufferAddress(buffer);
+    printf("address = %p\n", address);
+
+    overlay->queueBuffer(buffer);
+
+    return 0;
+}