Integrate from //sandbox/mathias/donut/...@145728

SurfaceFlinger rework for new EGL driver model support.
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index f944357..577dd4b 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -2,9 +2,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
+	BufferMapper.cpp \
 	Camera.cpp \
 	CameraParameters.cpp \
-	EGLDisplaySurface.cpp \
 	EGLNativeWindowSurface.cpp \
 	EventHub.cpp \
 	EventRecurrence.cpp \
diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp
new file mode 100644
index 0000000..a97188e
--- /dev/null
+++ b/libs/ui/BufferMapper.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BufferMapper"
+
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <utils/Log.h>
+
+#include <ui/BufferMapper.h>
+#include <ui/Rect.h>
+
+#include <EGL/android_natives.h>
+
+#include <hardware/gralloc.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+BufferMapper::BufferMapper()
+    : mAllocMod(0)
+{
+    hw_module_t const* module;
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+    if (err == 0) {
+        mAllocMod = (gralloc_module_t const *)module;
+    }
+}
+
+status_t BufferMapper::map(buffer_handle_t handle, void** addr)
+{
+    Mutex::Autolock _l(mLock);
+    status_t err = mAllocMod->map(mAllocMod, handle, addr);
+    LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+status_t BufferMapper::unmap(buffer_handle_t handle)
+{
+    Mutex::Autolock _l(mLock);
+    status_t err = mAllocMod->unmap(mAllocMod, handle);
+    LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+status_t BufferMapper::lock(buffer_handle_t handle, int usage, const Rect& bounds)
+{
+    status_t err = mAllocMod->lock(mAllocMod, handle, usage,
+            bounds.left, bounds.top, bounds.width(), bounds.height());
+    LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+status_t BufferMapper::unlock(buffer_handle_t handle)
+{
+    status_t err = mAllocMod->unlock(mAllocMod, handle);
+    LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp
deleted file mode 100644
index d06c98b..0000000
--- a/libs/ui/EGLDisplaySurface.cpp
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- **
- ** Copyright 2007 The Android Open Source Project
- **
- ** Licensed under the Apache License Version 2.0(the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- **     http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing software
- ** distributed under the License is distributed on an "AS IS" BASIS
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#define LOG_TAG "EGLDisplaySurface"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-
-#include <cutils/log.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-
-#include <hardware/copybit.h>
-
-#include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <ui/EGLDisplaySurface.h>
-
-#if HAVE_ANDROID_OS
-#include <linux/msm_mdp.h>
-#endif
-
-#include <EGL/egl.h>
-
-#include <pixelflinger/format.h>
-
-
-// ----------------------------------------------------------------------------
-
-egl_native_window_t* android_createDisplaySurface()
-{
-    egl_native_window_t* s = new android::EGLDisplaySurface();
-    s->memory_type = NATIVE_MEMORY_TYPE_GPU;
-    return s;
-}
-
-#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
-#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-EGLDisplaySurface::EGLDisplaySurface()
-    : EGLNativeSurface<EGLDisplaySurface>()
-{
-    egl_native_window_t::version = sizeof(egl_native_window_t);
-    egl_native_window_t::ident = 0;
-    egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef;
-    egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef;
-    egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers;
-    egl_native_window_t::connect = 0;
-    egl_native_window_t::disconnect = 0;
-
-    mFb[0].data = 0;
-    mFb[1].data = 0;
-    mBlitEngine = 0;
-    egl_native_window_t::fd = mapFrameBuffer();
-    if (egl_native_window_t::fd >= 0) {
-        
-        hw_module_t const* module;
-        if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
-            copybit_open(module, &mBlitEngine);
-        }
-        
-        const float in2mm = 25.4f;
-        float refreshRate = 1000000000000000LLU / (
-                float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres )
-                * ( mInfo.left_margin  + mInfo.right_margin + mInfo.xres )
-                * mInfo.pixclock);
-
-        const GGLSurface& buffer = mFb[1 - mIndex];
-        egl_native_window_t::width  = buffer.width;
-        egl_native_window_t::height = buffer.height;
-        egl_native_window_t::stride = buffer.stride;
-        egl_native_window_t::format = buffer.format;
-        egl_native_window_t::base   = intptr_t(mFb[0].data);
-        egl_native_window_t::offset =
-            intptr_t(buffer.data) - egl_native_window_t::base;
-        egl_native_window_t::flags  = 0;
-        egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width;
-        egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height;
-        egl_native_window_t::fps  = refreshRate;
-        egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB;
-        // no error, set the magic word
-        egl_native_window_t::magic = 0x600913;
-    }
-    mSwapCount = -1;
-    mPageFlipCount = 0;
-}
-
-EGLDisplaySurface::~EGLDisplaySurface()
-{
-    magic = 0;
-    copybit_close(mBlitEngine);
-    mBlitEngine = 0;
-    close(egl_native_window_t::fd);
-    munmap(mFb[0].data, mSize);
-    if (!(mFlags & PAGE_FLIP))
-        free((void*)mFb[1].data);
-}
-
-void EGLDisplaySurface::hook_incRef(NativeWindowType window) {
-    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
-    that->incStrong(that);
-}
-void EGLDisplaySurface::hook_decRef(NativeWindowType window) {
-    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
-    that->decStrong(that);
-}
-uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) {
-    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
-    return that->swapBuffers();
-}
-
-void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h)
-{
-    mInfo.reserved[0] = 0x54445055; // "UPDT";
-    mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
-    mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
-}
-
-uint32_t EGLDisplaySurface::swapBuffers()
-{
-#define SHOW_FPS 0
-#if SHOW_FPS
-    nsecs_t now = systemTime();
-    if (mSwapCount == -1) {
-        mTime = now;
-        mSwapCount = 0;
-        mSleep = 0;
-    } else {
-        nsecs_t d = now-mTime;
-        if (d >= seconds(1)) {
-            double fps = (mSwapCount * double(seconds(1))) / double(d);
-            LOGD("%f fps, sleep=%d / frame",
-                    fps, (int)ns2us(mSleep / mSwapCount));
-            mSwapCount = 0;
-            mTime = now;
-            mSleep = 0;
-        } else {
-            mSwapCount++;
-        }
-    }
-#endif
-    /* If we can't do the page_flip, just copy the back buffer to the front */
-    if (!(mFlags & PAGE_FLIP)) {
-        memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2);
-        return 0;
-    }
-
-    // do the actual flip
-    mIndex = 1 - mIndex;
-    mInfo.activate = FB_ACTIVATE_VBL;
-    mInfo.yoffset = mIndex ? mInfo.yres : 0;
-    if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) {
-        LOGE("FBIOPUT_VSCREENINFO failed");
-        return 0;
-    }
-
-    /*
-     * this is a monstrous hack: Because the h/w accelerator is not able
-     * to render directly into the framebuffer, we need to copy its
-     * internal framebuffer out to the fb.
-     * oem[0] is used to access the fd of internal fb.
-     * All this is needed only in standalone mode, in SurfaceFlinger mode
-     * we control where the GPU renders.
-     * We do this only if we have copybit, since this hack is needed only
-     * with msm7k.
-     */
-    if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0] && mBlitEngine) {
-        copybit_device_t *copybit = mBlitEngine;
-        copybit_rect_t sdrect = { 0, 0,
-                egl_native_window_t::width, egl_native_window_t::height };
-        copybit_image_t dst = {
-                egl_native_window_t::width,
-                egl_native_window_t::height,
-                egl_native_window_t::format,
-                egl_native_window_t::offset,
-                (void*)egl_native_window_t::base,
-                egl_native_window_t::fd
-        };
-        copybit_image_t src = {
-                egl_native_window_t::width,
-                egl_native_window_t::height,
-                egl_native_window_t::format, // XXX: use proper format
-                egl_native_window_t::offset,
-                (void*)egl_native_window_t::base,  // XXX: use proper base
-                egl_native_window_t::oem[0]
-        };
-        region_iterator it(Region(Rect(
-                egl_native_window_t::width, egl_native_window_t::height)));
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
-        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
-        copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it);
-    }
-
-    // update the address of the buffer to draw to next
-    const GGLSurface& buffer = mFb[1 - mIndex];
-    egl_native_window_t::offset =
-        intptr_t(buffer.data) - egl_native_window_t::base;
-
-#if SHOW_FPS
-    mSleep += systemTime()-now;
-#endif
-
-    mPageFlipCount++;
-
-    // We don't support screen-size changes for now
-    return 0;
-}
-
-int32_t EGLDisplaySurface::getPageFlipCount() const
-{
-    return mPageFlipCount;
-}
-
-void EGLDisplaySurface::copyFrontToBack(const Region& copyback)
-{
-#if HAVE_ANDROID_OS
-    if (mBlitEngine) {
-        copybit_image_t dst = {
-                w:      egl_native_window_t::stride,
-                h:      egl_native_window_t::height,
-                format: egl_native_window_t::format,
-                offset: mFb[1-mIndex].data - mFb[0].data,
-                base:   (void*)egl_native_window_t::base,
-                fd:     egl_native_window_t::fd
-        };
-        copybit_image_t src = {
-                w:      egl_native_window_t::stride,
-                h:      egl_native_window_t::height,
-                format: egl_native_window_t::format,
-                offset: mFb[mIndex].data - mFb[0].data,
-                base:   (void*)egl_native_window_t::base,
-                fd:     egl_native_window_t::fd
-        };
-        region_iterator it(copyback);
-        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
-    } else
-#endif
-    {
-        /* no extra copy needed since we copied back to front instead of
-         * flipping */
-        if (!(mFlags & PAGE_FLIP)) {
-            return;
-        }
-
-        Region::iterator iterator(copyback);
-        if (iterator) {
-            Rect r;
-            uint8_t* const screen_src = mFb[  mIndex].data;
-            uint8_t* const screen_dst = mFb[1-mIndex].data;
-            const size_t bpp = bytesPerPixel(egl_native_window_t::format);
-            const size_t bpr = egl_native_window_t::stride * bpp;
-            while (iterator.iterate(&r)) {
-                ssize_t h = r.bottom - r.top;
-                if (h) {
-                    size_t size = (r.right - r.left) * bpp;
-                    size_t o = (r.left + egl_native_window_t::stride * r.top) * bpp;
-                    uint8_t* s = screen_src + o;
-                    uint8_t* d = screen_dst + o;
-                    if (size == bpr) {
-                        size *= h;
-                        h = 1;
-                    }
-                    do {
-                        memcpy(d, s, size);
-                        d += bpr;
-                        s += bpr;
-                    } while (--h > 0);
-                }
-            }
-        }
-    }
-}
-
-void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst)
-{
-#if HAVE_ANDROID_OS
-    if (mBlitEngine) {
-        copybit_image_t src = {
-                w:      egl_native_window_t::stride,
-                h:      egl_native_window_t::height,
-                format: egl_native_window_t::format,
-                offset: mFb[mIndex].data - mFb[0].data,
-                base:   (void*)egl_native_window_t::base,
-                fd:     egl_native_window_t::fd
-        };
-        region_iterator it(Region(Rect(
-                egl_native_window_t::width, egl_native_window_t::height)));
-        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
-    } else
-#endif
-    {
-        uint8_t* const screen_src = mFb[  mIndex].data;
-        const size_t bpp = bytesPerPixel(egl_native_window_t::format);
-        const size_t bpr = egl_native_window_t::stride * bpp;
-        memcpy((char*)dst.base + dst.offset, screen_src,
-                bpr*egl_native_window_t::height);
-    }
-}
-
-void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst)
-{
-#if HAVE_ANDROID_OS
-    if (mBlitEngine) {
-        copybit_image_t src = {
-                w:      egl_native_window_t::stride,
-                h:      egl_native_window_t::height,
-                format: egl_native_window_t::format,
-                offset: mFb[1-mIndex].data - mFb[0].data,
-                base:   (void*)egl_native_window_t::base,
-                fd:     egl_native_window_t::fd
-        };
-        region_iterator it(Region(Rect(
-                egl_native_window_t::width, egl_native_window_t::height)));
-        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
-    } else
-#endif
-    {
-        uint8_t* const screen_src = mFb[1-mIndex].data;
-        const size_t bpp = bytesPerPixel(egl_native_window_t::format);
-        const size_t bpr = egl_native_window_t::stride * bpp;
-        memcpy((char*)dst.base + dst.offset, screen_src,
-                bpr*egl_native_window_t::height);
-    }
-}
-
-
-status_t EGLDisplaySurface::mapFrameBuffer()
-{
-    char const * const device_template[] = {
-            "/dev/graphics/fb%u",
-            "/dev/fb%u",
-            0 };
-    int fd = -1;
-    int i=0;
-    char name[64];
-    while ((fd==-1) && device_template[i]) {
-        snprintf(name, 64, device_template[i], 0);
-        fd = open(name, O_RDWR, 0);
-        i++;
-    }
-    if (fd < 0)
-        return -errno;
-
-    struct fb_fix_screeninfo finfo;
-    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
-        return -errno;
-
-    struct fb_var_screeninfo info;
-    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
-        return -errno;
-
-    info.reserved[0] = 0;
-    info.reserved[1] = 0;
-    info.reserved[2] = 0;
-    info.xoffset = 0;
-    info.yoffset = 0;
-    info.yres_virtual = info.yres * 2;
-    info.bits_per_pixel = 16;
-    /* Explicitly request 5/6/5 */
-    info.red.offset = 11;
-    info.red.length = 5;
-    info.green.offset = 5;
-    info.green.length = 6;
-    info.blue.offset = 0;
-    info.blue.length = 5;
-    info.transp.offset = 0;
-    info.transp.length = 0;
-    info.activate = FB_ACTIVATE_NOW;
-
-    uint32_t flags = PAGE_FLIP;
-    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
-        info.yres_virtual = info.yres;
-        flags &= ~PAGE_FLIP;
-        LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
-    }
-
-    if (info.yres_virtual < info.yres * 2) {
-        info.yres_virtual = info.yres;
-        flags &= ~PAGE_FLIP;
-        LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
-                info.yres_virtual, info.yres*2);
-    }
-
-    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
-        return -errno;
-
-    int refreshRate = 1000000000000000LLU /
-    (
-            uint64_t( info.upper_margin + info.lower_margin + info.yres )
-            * ( info.left_margin  + info.right_margin + info.xres )
-            * info.pixclock
-    );
-
-    if (refreshRate == 0) {
-        // bleagh, bad info from the driver
-        refreshRate = 60*1000;  // 60 Hz
-    }
-    if (int(info.width) <= 0 || int(info.height) <= 0) {
-        // the driver doesn't return that information
-        // default to 160 dpi
-        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
-        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
-    }
-
-    float xdpi = (info.xres * 25.4f) / info.width;
-    float ydpi = (info.yres * 25.4f) / info.height;
-    float fps  = refreshRate / 1000.0f;
-
-    LOGI(   "using (fd=%d)\n"
-            "id           = %s\n"
-            "xres         = %d px\n"
-            "yres         = %d px\n"
-            "xres_virtual = %d px\n"
-            "yres_virtual = %d px\n"
-            "bpp          = %d\n"
-            "r            = %2u:%u\n"
-            "g            = %2u:%u\n"
-            "b            = %2u:%u\n",
-            fd,
-            finfo.id,
-            info.xres,
-            info.yres,
-            info.xres_virtual,
-            info.yres_virtual,
-            info.bits_per_pixel,
-            info.red.offset, info.red.length,
-            info.green.offset, info.green.length,
-            info.blue.offset, info.blue.length
-    );
-
-    LOGI(   "width        = %d mm (%f dpi)\n"
-            "height       = %d mm (%f dpi)\n"
-            "refresh rate = %.2f Hz\n",
-            info.width,  xdpi,
-            info.height, ydpi,
-            fps
-    );
-
-
-    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
-        return -errno;
-
-    if (finfo.smem_len <= 0)
-        return -errno;
-
-    /*
-     * Open and map the display.
-     */
-
-    void* buffer  = (uint16_t*) mmap(
-            0, finfo.smem_len,
-            PROT_READ | PROT_WRITE,
-            MAP_SHARED,
-            fd, 0);
-
-    if (buffer == MAP_FAILED)
-        return -errno;
-
-    // at least for now, always clear the fb
-    memset(buffer, 0, finfo.smem_len);
-
-    uint8_t* offscreen[2];
-    offscreen[0] = (uint8_t*)buffer;
-    if (flags & PAGE_FLIP) {
-        offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres;
-    } else {
-        offscreen[1] = (uint8_t*)malloc(finfo.smem_len);
-        if (offscreen[1] == 0) {
-            munmap(buffer, finfo.smem_len);
-            return NO_MEMORY;
-        }
-    }
-
-    mFlags = flags;
-    mInfo = info;
-    mFinfo = finfo;
-    mSize = finfo.smem_len;
-    mIndex = 0;
-    for (int i=0 ; i<2 ; i++) {
-        mFb[i].version = sizeof(GGLSurface);
-        mFb[i].width   = info.xres;
-        mFb[i].height  = info.yres;
-        mFb[i].stride  = finfo.line_length / (info.bits_per_pixel >> 3);
-        mFb[i].data    = (GGLubyte*)(offscreen[i]);
-        mFb[i].format  = GGL_PIXEL_FORMAT_RGB_565;
-    }
-    return fd;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp
index f1071cf..5d9d6a4 100644
--- a/libs/ui/EGLNativeWindowSurface.cpp
+++ b/libs/ui/EGLNativeWindowSurface.cpp
@@ -20,142 +20,225 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 
 #include <cutils/log.h>
 #include <cutils/atomic.h>
+#include <utils/threads.h>
 
 #include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
+#include <ui/EGLNativeWindowSurface.h>
 
 #include <EGL/egl.h>
 
 #include <pixelflinger/format.h>
+#include <pixelflinger/pixelflinger.h>
 
-#include <ui/EGLNativeWindowSurface.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
 
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface)
-    : EGLNativeSurface<EGLNativeWindowSurface>(),
-    mSurface(surface), mConnected(false)
-{
-    egl_native_window_t::magic = 0x600913;
-    egl_native_window_t::version = sizeof(egl_native_window_t);
-    egl_native_window_t::ident = 0;
-    egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef;
-    egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef;
-    egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers;
-    egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect;
-    egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect;
-    
-    DisplayInfo dinfo;
-    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
-    egl_native_window_t::xdpi = dinfo.xdpi;
-    egl_native_window_t::ydpi = dinfo.ydpi;
-    egl_native_window_t::fps  = dinfo.fps;
-    egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER;
-}
+/*
+ * This implements the (main) framebuffer management. This class is used
+ * mostly by SurfaceFlinger, but also by command line GL application.
+ * 
+ * In fact this is an implementation of android_native_window_t on top of
+ * the framebuffer.
+ * 
+ * Currently it is pretty simple, it manages only two buffers (the front and 
+ * back buffer).
+ * 
+ */
 
-EGLNativeWindowSurface::~EGLNativeWindowSurface()
+FramebufferNativeWindow::FramebufferNativeWindow() 
+    : BASE(), fbDev(0), grDev(0)
 {
-    disconnect();
-    mSurface.clear();
-    magic = 0;
-}
+    hw_module_t const* module;
+    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+        int stride;
+        framebuffer_open(module, &fbDev);
+        gralloc_open(module, &grDev);
+        int err;
 
-void EGLNativeWindowSurface::hook_incRef(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->incStrong(that);
-}
+        
+        // initialize the buffer FIFO
+        mNumBuffers = 2;
+        mNumFreeBuffers = 2;
+        mBufferHead = mNumBuffers-1;
+        buffers[0] = new NativeBuffer(
+                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        buffers[1] = new NativeBuffer(
+                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        
+        err = grDev->alloc(grDev,
+                fbDev->width, fbDev->height, fbDev->format, 
+                GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
 
-void EGLNativeWindowSurface::hook_decRef(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->decStrong(that);
-}
+        LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
+                fbDev->width, fbDev->height, strerror(-err));
 
-void EGLNativeWindowSurface::hook_connect(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->connect();
-}
+        err = grDev->alloc(grDev,
+                fbDev->width, fbDev->height, fbDev->format, 
+                GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
 
-void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->disconnect();
-}
+        LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
+                fbDev->width, fbDev->height, strerror(-err));
 
-uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    return that->swapBuffers();
-}
+        gralloc_module_t* m = 
+            reinterpret_cast<gralloc_module_t*>(grDev->common.module);
 
-void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h)
-{
-    mSurface->setSwapRectangle(Rect(l, t, l+w, t+h));
-}
-
-uint32_t EGLNativeWindowSurface::swapBuffers()
-{
-    const int w = egl_native_window_t::width;
-    const int h = egl_native_window_t::height;
-    const sp<Surface>& surface(mSurface);
-    Surface::SurfaceInfo info;
-    surface->unlockAndPost();
-    surface->lock(&info);
-    // update the address of the buffer to draw to next
-    egl_native_window_t::base   = intptr_t(info.base);
-    egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
-    
-    // update size if it changed
-    if (w != int(info.w) || h != int(info.h)) {
-        egl_native_window_t::width  = info.w;
-        egl_native_window_t::height = info.h;
-        egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
-        egl_native_window_t::format = info.format;
-        return EGL_NATIVES_FLAG_SIZE_CHANGED;
+        // FIXME: do we actually need to map the framebuffer?
+        m->map(m, buffers[0]->handle, &buffers[0]->bits);
+        m->map(m, buffers[1]->handle, &buffers[1]->bits);
     }
+
+    uint32_t flags = fbDev->flags & SURFACE_FLAG_MAPPED;
+    
+    /*
+     * FIXME: SURFACE_FLAG_PRESERVE_CONTENT
+     * how to implement this, there is no concept of preserve content in
+     * the framebuffer, which just "posts" buffer.
+     * 
+     * It looks like what we need is a way to know if the posted buffer can
+     * be reused. But if so, why allocating 2 buffers?...
+     * 
+     * should the lock/unlock calls take care of the copy-back?
+     * 
+     * 
+     * In the end, the client wants to know if the backbuffer is preserved
+     * though... it's complicated.
+     * 
+     */
+    
+    //flags |= SURFACE_FLAG_PRESERVE_CONTENT;
+    
+
+    const_cast<uint32_t&>(android_native_window_t::flags) = flags; 
+    const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
+    const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi;
+    const_cast<int&>(android_native_window_t::minSwapInterval) = 
+        fbDev->minSwapInterval;
+    const_cast<int&>(android_native_window_t::maxSwapInterval) = 
+        fbDev->maxSwapInterval;
+
+    android_native_window_t::connect = connect;
+    android_native_window_t::disconnect = disconnect;
+    android_native_window_t::setSwapInterval = setSwapInterval;
+    android_native_window_t::setSwapRectangle = setSwapRectangle;
+    android_native_window_t::dequeueBuffer = dequeueBuffer;
+    android_native_window_t::lockBuffer = lockBuffer;
+    android_native_window_t::queueBuffer = queueBuffer;
+}
+
+FramebufferNativeWindow::~FramebufferNativeWindow() {
+    grDev->free(grDev, buffers[0]->handle);
+    grDev->free(grDev, buffers[1]->handle);
+    gralloc_module_t* m = 
+        reinterpret_cast<gralloc_module_t*>(grDev->common.module);
+    m->unmap(m, buffers[0]->handle);
+    m->unmap(m, buffers[1]->handle);
+    gralloc_close(grDev);
+    framebuffer_close(fbDev);
+}
+
+void FramebufferNativeWindow::connect(android_native_window_t* window) 
+{
+}
+
+void FramebufferNativeWindow::disconnect(android_native_window_t* window) 
+{
+}
+
+int FramebufferNativeWindow::setSwapInterval(
+        android_native_window_t* window, int interval) 
+{
+    framebuffer_device_t* fb = getSelf(window)->fbDev;
+    return fb->setSwapInterval(fb, interval);
+}
+
+int FramebufferNativeWindow::setSwapRectangle(android_native_window_t* window,
+        int l, int t, int w, int h)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    self->mDirty = Rect(l, t, l+w, t+h); 
     return 0;
 }
 
-void EGLNativeWindowSurface::connect()
-{   
-    if (!mConnected) {
-        Surface::SurfaceInfo info;
-        mSurface->lock(&info);
-        mSurface->setSwapRectangle(Rect(info.w, info.h));
-        mConnected = true;
+int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, 
+        android_native_buffer_t** buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
 
-        egl_native_window_t::width  = info.w;
-        egl_native_window_t::height = info.h;
-        egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
-        egl_native_window_t::format = info.format;
-        egl_native_window_t::base   = intptr_t(info.base);
-        egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
-        // FIXME: egl_native_window_t::memory_type used to be set from
-        // mSurface, but we wanted to break this dependency. We set it to
-        // GPU because the software rendered doesn't care, but the h/w
-        // accelerator needs it. Eventually, this value should go away
-        // completely, since memory will be managed by OpenGL.
-        egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU; 
-        egl_native_window_t::fd = 0;
+    // wait for a free buffer
+    while (!self->mNumFreeBuffers) {
+        self->mCondition.wait(self->mutex);
     }
+    // get this buffer
+    self->mNumFreeBuffers--;
+    int index = self->mBufferHead++;
+    if (self->mBufferHead >= self->mNumBuffers)
+        self->mBufferHead = 0;
+
+    *buffer = self->buffers[index].get();
+
+    return 0;
 }
 
-void EGLNativeWindowSurface::disconnect()
+int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
 {
-    if (mConnected) {
-        mSurface->unlock();
-        mConnected = false;
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+
+    // wait that the buffer we're locking is not front anymore
+    while (self->front == buffer) {
+        self->mCondition.wait(self->mutex);
     }
+        
+    gralloc_module_t* m = 
+        reinterpret_cast<gralloc_module_t*>(self->grDev->common.module);
+    const Rect& dirty(self->mDirty);
+
+    buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
+    int res = m->lock(m, handle, GRALLOC_USAGE_HW_FB,
+            dirty.left, dirty.right, dirty.width(), dirty.height());
+    
+    return res;
+}
+
+int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
+    gralloc_module_t* m = 
+        reinterpret_cast<gralloc_module_t*>(self->grDev->common.module);
+
+    buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
+    m->unlock(m, handle);
+    int res = fb->post(fb, handle);
+
+    self->front = static_cast<NativeBuffer*>(buffer);
+    self->mNumFreeBuffers++;
+    self->mCondition.broadcast();
+    return res;
 }
 
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
+
+
+EGLNativeWindowType android_createDisplaySurface(void)
+{
+    return new android::FramebufferNativeWindow();
+}
+
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index d5e9f81..fcea8ec 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "ISurface"
+
 #include <stdio.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -23,10 +25,13 @@
 
 #include <ui/ISurface.h>
 #include <ui/Overlay.h>
+#include <ui/Surface.h>
 
 
 namespace android {
 
+// ----------------------------------------------------------------------
+
 ISurface::BufferHeap::BufferHeap() 
     : w(0), h(0), hor_stride(0), ver_stride(0), format(0),
     transform(0), flags(0) 
@@ -55,6 +60,8 @@
 {     
 }
 
+// ----------------------------------------------------------------------
+
 class BpSurface : public BpInterface<ISurface>
 {
 public:
@@ -63,6 +70,15 @@
     {
     }
 
+    virtual sp<SurfaceBuffer> getBuffer()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        remote()->transact(GET_BUFFER, data, &reply);
+        sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply);
+        return buffer;
+    }
+
     virtual status_t registerBuffers(const BufferHeap& buffers)
     {
         Parcel data, reply;
@@ -122,6 +138,11 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
+        case GET_BUFFER: {
+            CHECK_INTERFACE(ISurface, data, reply);
+            sp<SurfaceBuffer> buffer(getBuffer());
+            return SurfaceBuffer::writeToParcel(reply, buffer.get());
+        }
         case REGISTER_BUFFERS: {
             CHECK_INTERFACE(ISurface, data, reply);
             BufferHeap buffer;
diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp
index 76597e1..1932bf9 100644
--- a/libs/ui/ISurfaceComposer.cpp
+++ b/libs/ui/ISurfaceComposer.cpp
@@ -114,36 +114,6 @@
         remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
     }
 
-    virtual status_t requestGPU(
-            const sp<IGPUCallback>& callback, gpu_info_t* gpu)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeStrongBinder(callback->asBinder());
-        remote()->transact(BnSurfaceComposer::REQUEST_GPU, data, &reply);
-        gpu->regs = interface_cast<IMemory>(reply.readStrongBinder());
-        gpu->count = reply.readInt32();
-
-        // FIXME: for now, we don't dynamically allocate the regions array
-        size_t maxCount = sizeof(gpu->regions)/sizeof(*gpu->regions);
-        if (gpu->count > maxCount)
-            return BAD_VALUE;
-
-        for (size_t i=0 ; i<gpu->count ; i++) {
-            gpu->regions[i].region = interface_cast<IMemory>(reply.readStrongBinder());
-            gpu->regions[i].reserved = reply.readInt32();
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t revokeGPU()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        remote()->transact(BnSurfaceComposer::REVOKE_GPU, data, &reply);
-        return reply.readInt32();
-    }
-
     virtual void signal() const
     {
         Parcel data, reply;
@@ -201,9 +171,6 @@
         case BOOT_FINISHED: {
             bootFinished();
         } break;
-        case REVOKE_GPU: {
-            reply->writeInt32( revokeGPU() );
-        } break;
         case SIGNAL: {
             signal();
         } break;
@@ -211,26 +178,6 @@
             sp<IBinder> b = getCblk()->asBinder();
             reply->writeStrongBinder(b);
         } break;
-        case REQUEST_GPU: {
-            // TODO: this should be protected by a permission
-            gpu_info_t info;
-            sp<IGPUCallback> callback
-                = interface_cast<IGPUCallback>(data.readStrongBinder());
-            status_t res = requestGPU(callback, &info);
-
-            // FIXME: for now, we don't dynamically allocate the regions array
-            size_t maxCount = sizeof(info.regions)/sizeof(*info.regions);
-            if (info.count > maxCount)
-                return BAD_VALUE;
-
-            reply->writeStrongBinder(info.regs->asBinder());
-            reply->writeInt32(info.count);
-            for (size_t i=0 ; i<info.count ; i++) {
-                reply->writeStrongBinder(info.regions[i].region->asBinder());
-                reply->writeInt32(info.regions[i].reserved);
-            }
-            reply->writeInt32(res);
-        } break;
         default:
             return UNKNOWN_TRANSACTION;
     }
@@ -239,41 +186,4 @@
 
 // ----------------------------------------------------------------------------
 
-enum {
-    // Note: BOOT_FINISHED must remain this value, it is called by ActivityManagerService.
-    GPU_LOST = IBinder::FIRST_CALL_TRANSACTION
-};
-
-class BpGPUCallback : public BpInterface<IGPUCallback>
-{
-public:
-    BpGPUCallback(const sp<IBinder>& impl)
-        : BpInterface<IGPUCallback>(impl)
-    {
-    }
-
-    virtual void gpuLost()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGPUCallback::getInterfaceDescriptor());
-        remote()->transact(GPU_LOST, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(GPUCallback, "android.ui.IGPUCallback");
-
-status_t BnGPUCallback::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case GPU_LOST: {
-            CHECK_INTERFACE(IGPUCallback, data, reply);
-            gpuLost();
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
 };
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
index dd6a798..597b87e 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -191,8 +191,6 @@
 {
     token = parcel.readInt32();
     identity  = parcel.readInt32();
-    heap[0] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
-    heap[1] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
     return NO_ERROR;
 }
 
@@ -200,8 +198,6 @@
 {
     parcel->writeInt32(token);
     parcel->writeInt32(identity);
-    parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL);
-    parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL);
     return NO_ERROR;
 }
 
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index b236edc..59c6514 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -129,12 +129,8 @@
 OverlayRef::~OverlayRef()
 {
     if (mOwnHandle) {
-        /* FIXME: handles should be promoted to "real" API and be handled by 
-         * the framework */
-        for (int i=0 ; i<mOverlayHandle->numFds ; i++) {
-            close(mOverlayHandle->data[i]);
-        }
-        free((void*)mOverlayHandle);
+        native_handle_close(mOverlayHandle);
+        native_handle_delete(const_cast<native_handle*>(mOverlayHandle));
     }
 }
 
@@ -147,7 +143,7 @@
         uint32_t f = data.readInt32();
         uint32_t ws = data.readInt32();
         uint32_t hs = data.readInt32();
-        native_handle* handle = data.readNativeHandle(NULL, NULL);
+        native_handle* handle = data.readNativeHandle();
 
         result = new OverlayRef();
         result->mOverlayHandle = handle;
@@ -169,7 +165,7 @@
         reply->writeInt32(o->mFormat);
         reply->writeInt32(o->mWidthStride);
         reply->writeInt32(o->mHeightStride);
-        reply->writeNativeHandle(*(o->mOverlayHandle));
+        reply->writeNativeHandle(o->mOverlayHandle);
     } else {
         reply->writeStrongBinder(NULL);
     }
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 4ea9ae2..357e4d0 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -23,24 +23,126 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <utils/Atomic.h>
 #include <utils/Errors.h>
 #include <utils/threads.h>
 #include <utils/IPCThreadState.h>
 #include <utils/IMemory.h>
 #include <utils/Log.h>
 
+#include <ui/DisplayInfo.h>
+#include <ui/BufferMapper.h>
+#include <ui/EGLNativeWindowSurface.h>
 #include <ui/ISurface.h>
 #include <ui/Surface.h>
 #include <ui/SurfaceComposerClient.h>
 #include <ui/Rect.h>
 
+#include <EGL/android_natives.h>
+
 #include <private/ui/SharedState.h>
 #include <private/ui/LayerState.h>
 
+#include <pixelflinger/pixelflinger.h>
+
 namespace android {
 
-// ---------------------------------------------------------------------------
+// ============================================================================
+//  SurfaceBuffer
+// ============================================================================
+
+SurfaceBuffer::SurfaceBuffer() 
+    : BASE(), handle(0), mOwner(false)
+{
+    width  = 
+    height = 
+    stride = 
+    format = 
+    usage  = 0;
+    android_native_buffer_t::getHandle = getHandle;
+}
+
+SurfaceBuffer::SurfaceBuffer(const Parcel& data) 
+    : BASE(), handle(0), mOwner(true)
+{
+    // we own the handle in this case
+    width  = data.readInt32();
+    height = data.readInt32();
+    stride = data.readInt32();
+    format = data.readInt32();
+    usage  = data.readInt32();
+    handle = data.readNativeHandle();
+    android_native_buffer_t::getHandle = getHandle;
+}
+
+SurfaceBuffer::~SurfaceBuffer()
+{
+    if (handle && mOwner) {
+        native_handle_close(handle);
+        native_handle_delete(const_cast<native_handle*>(handle));
+    }
+}
+
+int SurfaceBuffer::getHandle(android_native_buffer_t const * base, 
+        buffer_handle_t* handle)
+{
+    *handle = getSelf(base)->handle;
+    return 0;
+}
+
+status_t SurfaceBuffer::writeToParcel(Parcel* reply, 
+        android_native_buffer_t const* buffer)
+{
+    buffer_handle_t handle;
+    status_t err = buffer->getHandle(buffer, &handle);
+    if (err < 0) {
+        return err;
+    }
+    reply->writeInt32(buffer->width);
+    reply->writeInt32(buffer->height);
+    reply->writeInt32(buffer->stride);
+    reply->writeInt32(buffer->format);
+    reply->writeInt32(buffer->usage);
+    reply->writeNativeHandle(handle);
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------
+
+static void copyBlt(const android_native_buffer_t* dst,
+        const android_native_buffer_t* src, const Region& reg)
+{
+    Region::iterator iterator(reg);
+    if (iterator) {
+        // NOTE: dst and src must be the same format
+        Rect r;
+        const size_t bpp = bytesPerPixel(src->format);
+        const size_t dbpr = dst->stride * bpp;
+        const size_t sbpr = src->stride * bpp;
+        while (iterator.iterate(&r)) {
+            ssize_t h = r.bottom - r.top;
+            if (h) {
+                size_t size = (r.right - r.left) * bpp;
+                uint8_t* s = (GGLubyte*)src->bits + 
+                        (r.left + src->stride * r.top) * bpp;
+                uint8_t* d = (GGLubyte*)dst->bits +
+                        (r.left + dst->stride * r.top) * bpp;
+                if (dbpr==sbpr && size==sbpr) {
+                    size *= h;
+                    h = 1;
+                }
+                do {
+                    memcpy(d, s, size);
+                    d += dbpr;
+                    s += sbpr;
+                } while (--h > 0);
+            }
+        }
+    }
+}
+
+// ============================================================================
+//  Surface
+// ============================================================================
 
 Surface::Surface(const sp<SurfaceComposerClient>& client, 
         const sp<ISurface>& surface,
@@ -51,26 +153,44 @@
       mToken(data.token), mIdentity(data.identity),
       mFormat(format), mFlags(flags), mOwner(owner)
 {
+    android_native_window_t::connect          = connect;
+    android_native_window_t::disconnect       = disconnect;
+    android_native_window_t::setSwapInterval  = setSwapInterval;
+    android_native_window_t::setSwapRectangle = setSwapRectangle;
+    android_native_window_t::dequeueBuffer    = dequeueBuffer;
+    android_native_window_t::lockBuffer       = lockBuffer;
+    android_native_window_t::queueBuffer      = queueBuffer;
+
     mSwapRectangle.makeInvalid();
-    mSurfaceHeapBase[0] = 0;
-    mSurfaceHeapBase[1] = 0;
-    mHeap[0] = data.heap[0]; 
-    mHeap[1] = data.heap[1];
+
+    DisplayInfo dinfo;
+    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
+    const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
+    const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
+    // FIXME: set real values here
+    const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
+    const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
+    const_cast<uint32_t&>(android_native_window_t::flags) = 0;
 }
 
 Surface::Surface(Surface const* rhs)
     : mOwner(false)
 {
-    mToken   = rhs->mToken;
-    mIdentity= rhs->mIdentity;
-    mClient  = rhs->mClient;
-    mSurface = rhs->mSurface;
-    mHeap[0] = rhs->mHeap[0];
-    mHeap[1] = rhs->mHeap[1];
-    mFormat  = rhs->mFormat;
-    mFlags   = rhs->mFlags;
-    mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0];
-    mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1];
+    // FIXME: we really should get rid of this ctor. the memcpy below
+    //should be safe for now, but android_native_window_t is not supposed
+    // to be clonable.
+    memcpy( static_cast<android_native_window_t*>(this),
+            static_cast<android_native_window_t const *>(rhs),
+            sizeof(android_native_window_t));
+
+    mToken      = rhs->mToken;
+    mIdentity   = rhs->mIdentity;
+    mClient     = rhs->mClient;
+    mSurface    = rhs->mSurface;
+    mBuffers[0] = rhs->mBuffers[0];
+    mBuffers[1] = rhs->mBuffers[1];
+    mFormat     = rhs->mFormat;
+    mFlags      = rhs->mFlags;
     mSwapRectangle.makeInvalid();
 }
 
@@ -78,21 +198,26 @@
 {
     if (mOwner && mToken>=0 && mClient!=0) {
         mClient->destroySurface(mToken);
+        if (mBuffers[0] != 0) {
+            BufferMapper::get().unmap(mBuffers[0]->getHandle());
+        }
+        if (mBuffers[1] != 0) {
+            BufferMapper::get().unmap(mBuffers[1]->getHandle());
+        }
     }
     mClient.clear();
     mSurface.clear();
-    mHeap[0].clear();
-    mHeap[1].clear();
     IPCThreadState::self()->flushCommands();
 }
 
 sp<Surface> Surface::dup() const
 {
+    // FIXME: we should get rid of Surface::dup()
     Surface const * r = this;
     if (this && mOwner) {
         // the only reason we need to do this is because of Java's garbage
         // collector: because we're creating a copy of the Surface
-        // instead of a reference, we can garantee that when our last
+        // instead of a reference, we can guarantee that when our last
         // reference goes away, the real surface will be deleted.
         // Without this hack (the code is correct too), we'd have to
         // wait for a GC for the surface to go away.
@@ -101,31 +226,244 @@
     return const_cast<Surface*>(r);
 }
 
-status_t Surface::nextBuffer(SurfaceInfo* info) {
-    return mClient->nextBuffer(this, info);
+status_t Surface::validate(per_client_cblk_t const* cblk) const
+{
+    if (cblk == 0) {
+        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
+        return NO_INIT;
+    }
+    status_t err = cblk->validate(mToken);
+    if (err != NO_ERROR) {
+        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+                mToken, mIdentity, err, strerror(-err));
+        return err;
+    }
+    if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
+        LOGE("using an invalid surface id=%d, identity=%u should be %d",
+                mToken, mIdentity, cblk->layers[mToken].identity);
+        return NO_INIT;
+    }
+    return NO_ERROR;
 }
 
+// ----------------------------------------------------------------------------
+
+int Surface::setSwapRectangle(android_native_window_t* window,
+        int l, int t, int w, int h)
+{
+    Surface* self = getSelf(window);
+    self->setSwapRectangle(Rect(l, t, l+w, t+h));
+    return 0;
+}
+
+void Surface::connect(android_native_window_t* window)
+{
+}
+
+void Surface::disconnect(android_native_window_t* window)
+{
+}
+
+int Surface::setSwapInterval(android_native_window_t* window, int interval)
+{
+    return 0;
+}
+
+int Surface::dequeueBuffer(android_native_window_t* window, 
+        android_native_buffer_t** buffer)
+{
+    Surface* self = getSelf(window);
+    return self->dequeueBuffer(buffer);
+}
+
+int Surface::lockBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    Surface* self = getSelf(window);
+    return self->lockBuffer(buffer);
+}
+
+int Surface::queueBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    Surface* self = getSelf(window);
+    return self->queueBuffer(buffer);
+}
+
+// ----------------------------------------------------------------------------
+
+int Surface::dequeueBuffer(android_native_buffer_t** buffer)
+{
+    // FIXME: dequeueBuffer() needs proper implementation
+
+    Mutex::Autolock _l(mSurfaceLock);
+
+    per_client_cblk_t* const cblk = mClient->mControl;
+    status_t err = validate(cblk);
+    if (err != NO_ERROR)
+        return err;
+
+    SurfaceID index(mToken); 
+    
+    int32_t backIdx = cblk->lock_layer(size_t(index),
+            per_client_cblk_t::BLOCKING);
+
+    if (backIdx < 0)
+        return status_t(backIdx); 
+
+    mBackbufferIndex = backIdx;
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+
+    volatile const surface_info_t* const back = lcblk->surface + backIdx;
+    if (back->flags & surface_info_t::eNeedNewBuffer) {
+        getBufferLocked(backIdx);
+    }
+
+    const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+    *buffer = backBuffer.get();
+
+    return NO_ERROR;
+}
+
+int Surface::lockBuffer(android_native_buffer_t* buffer)
+{
+    // FIXME: lockBuffer() needs proper implementation
+    return 0;
+}
+
+int Surface::queueBuffer(android_native_buffer_t* buffer)
+{   
+    Mutex::Autolock _l(mSurfaceLock);
+
+    per_client_cblk_t* const cblk = mClient->mControl;
+    status_t err = validate(cblk);
+    if (err != NO_ERROR)
+        return err;
+
+    // transmit the dirty region
+    const Region dirty(swapRectangle());
+    SurfaceID index(mToken); 
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+    _send_dirty_region(lcblk, dirty);
+
+    uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
+    if (!(newstate & eNextFlipPending))
+        mClient->signalServer();
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
 status_t Surface::lock(SurfaceInfo* info, bool blocking) {
     return Surface::lock(info, NULL, blocking);
 }
 
-status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->lockSurface(this, info, dirty, blocking);
+status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking) 
+{
+    // FIXME: needs some locking here
+    android_native_buffer_t* backBuffer;
+    status_t err = dequeueBuffer(&backBuffer);
+    if (err == NO_ERROR) {
+        err = lockBuffer(backBuffer);
+        if (err == NO_ERROR) {
+            backBuffer->common.incRef(&backBuffer->common);
+            mLockedBuffer = backBuffer;
+            other->w      = backBuffer->width;
+            other->h      = backBuffer->height;
+            other->s      = backBuffer->stride;
+            other->usage  = backBuffer->usage;
+            other->format = backBuffer->format;
+            other->bits   = backBuffer->bits;
+
+            // we handle copy-back here...
+            
+            const Rect bounds(backBuffer->width, backBuffer->height);
+            Region newDirtyRegion;
+
+            per_client_cblk_t* const cblk = mClient->mControl;
+            layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
+            volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
+            if (back->flags & surface_info_t::eBufferDirty) {
+                // content is meaningless in this case and the whole surface
+                // needs to be redrawn.
+                newDirtyRegion.set(bounds);
+                if (dirty) {
+                    *dirty = newDirtyRegion;
+                }
+            } else 
+            {
+                if (dirty) {
+                    dirty->andSelf(Region(bounds));
+                    newDirtyRegion = *dirty;
+                } else {
+                    newDirtyRegion.set(bounds);
+                }
+                Region copyback;
+                if (!(lcblk->flags & eNoCopyBack)) {
+                    const Region previousDirtyRegion(dirtyRegion());
+                    copyback = previousDirtyRegion.subtract(newDirtyRegion);
+                }
+                const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
+                if (!copyback.isEmpty() && frontBuffer!=0) {
+                    // copy front to back
+                    copyBlt(backBuffer, frontBuffer.get(), copyback);
+                }
+            }
+            setDirtyRegion(newDirtyRegion);
+
+
+            Rect lockBounds(backBuffer->width, backBuffer->height);
+            if (dirty) {
+                lockBounds = dirty->bounds();
+            }
+            buffer_handle_t handle;
+            backBuffer->getHandle(backBuffer, &handle);
+            status_t res = BufferMapper::get().lock(handle,
+                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 
+                    lockBounds);
+            LOGW_IF(res, "failed locking buffer %d (%p)", 
+                    mBackbufferIndex, handle);
+            setSwapRectangle(lockBounds);
+        }
+    }
+    return err;
+}
+    
+status_t Surface::unlockAndPost() 
+{
+    // FIXME: needs some locking here
+
+    if (mLockedBuffer == 0)
+        return BAD_VALUE;
+
+    buffer_handle_t handle;
+    mLockedBuffer->getHandle(mLockedBuffer, &handle);
+    status_t res = BufferMapper::get().unlock(handle);
+    LOGW_IF(res, "failed unlocking buffer %d (%p)",
+            mBackbufferIndex, handle);
+
+    const Rect dirty(dirtyRegion().bounds());
+    setSwapRectangle(dirty);
+    status_t err = queueBuffer(mLockedBuffer);
+    mLockedBuffer->common.decRef(&mLockedBuffer->common);
+    mLockedBuffer = 0;
+    return err;
 }
 
-status_t Surface::unlockAndPost() {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->unlockAndPostSurface(this);
+void Surface::_send_dirty_region(
+        layer_cblk_t* lcblk, const Region& dirty)
+{
+    const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
+    flat_region_t* flat_region = lcblk->region + index;
+    status_t err = dirty.write(flat_region, sizeof(flat_region_t));
+    if (err < NO_ERROR) {
+        // region doesn't fit, use the bounds
+        const Region reg(dirty.bounds());
+        reg.write(flat_region, sizeof(flat_region_t));
+    }
 }
 
-status_t Surface::unlock() {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->unlockSurface(this);
-}
 
 status_t Surface::setLayer(int32_t layer) {
     return mClient->setLayer(this, layer);
@@ -183,8 +521,6 @@
     ISurfaceFlingerClient::surface_data_t data;
     sp<IBinder> clientBinder= parcel->readStrongBinder();
     sp<ISurface> surface    = interface_cast<ISurface>(parcel->readStrongBinder());
-    data.heap[0]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
-    data.heap[1]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
     data.token              = parcel->readInt32();
     data.identity           = parcel->readInt32();
     PixelFormat format      = parcel->readInt32();
@@ -204,21 +540,16 @@
     uint32_t identity = 0;
     sp<SurfaceComposerClient> client;
     sp<ISurface> sur;
-    sp<IMemoryHeap> heap[2];
     if (surface->isValid()) {
         token = surface->mToken;
         identity = surface->mIdentity;
         client = surface->mClient;
         sur = surface->mSurface;
-        heap[0] = surface->mHeap[0];
-        heap[1] = surface->mHeap[1];
         format = surface->mFormat;
         flags = surface->mFlags;
     }
     parcel->writeStrongBinder(client!=0  ? client->connection() : NULL);
     parcel->writeStrongBinder(sur!=0     ? sur->asBinder()      : NULL);
-    parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder()  : NULL);
-    parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder()  : NULL);
     parcel->writeInt32(token);
     parcel->writeInt32(identity);
     parcel->writeInt32(format);
@@ -233,23 +564,24 @@
     return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
 }
 
-void* Surface::heapBase(int i) const 
+status_t Surface::getBufferLocked(int index)
 {
-    void* heapBase = mSurfaceHeapBase[i];
-    // map lazily so it doesn't get mapped in clients that don't need it
-    if (heapBase == 0) {
-        const sp<IMemoryHeap>& heap(mHeap[i]);
-        if (heap != 0) {
-            heapBase = static_cast<uint8_t*>(heap->base());
-            if (heapBase == MAP_FAILED) {
-                heapBase = NULL;
-                LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)",
-                        heap->asBinder().get(), heap.get());
-            }
-            mSurfaceHeapBase[i] = heapBase;
+    status_t err = NO_MEMORY;
+    sp<SurfaceBuffer> buffer = mSurface->getBuffer();
+    LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
+    if (buffer != 0) {
+        sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
+        if (currentBuffer != 0) {
+            BufferMapper::get().unmap(currentBuffer->getHandle());
+            currentBuffer.clear();
+        }
+        err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits);
+        LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
+        if (err == NO_ERROR) {
+            currentBuffer = buffer;
         }
     }
-    return heapBase;
+    return err; 
 }
 
 }; // namespace android
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp
index fe803ff..e1b13c7 100644
--- a/libs/ui/SurfaceComposerClient.cpp
+++ b/libs/ui/SurfaceComposerClient.cpp
@@ -29,27 +29,21 @@
 #include <utils/Errors.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
-#include <utils/IPCThreadState.h>
 #include <utils/IServiceManager.h>
 #include <utils/IMemory.h>
 #include <utils/Log.h>
 
+#include <ui/DisplayInfo.h>
 #include <ui/ISurfaceComposer.h>
 #include <ui/ISurfaceFlingerClient.h>
 #include <ui/ISurface.h>
 #include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
-#include <ui/Point.h>
 
 #include <private/ui/SharedState.h>
 #include <private/ui/LayerState.h>
 #include <private/ui/SurfaceFlingerSynchro.h>
 
-#include <pixelflinger/pixelflinger.h>
-
-#include <utils/BpBinder.h>
-
 #define VERBOSE(...)	((void)0)
 //#define VERBOSE			LOGD
 
@@ -109,50 +103,8 @@
 
 // ---------------------------------------------------------------------------
 
-static void copyBlt(const GGLSurface& dst,
-        const GGLSurface& src, const Region& reg)
-{
-    Region::iterator iterator(reg);
-    if (iterator) {
-        // NOTE: dst and src must be the same format
-        Rect r;
-        const size_t bpp = bytesPerPixel(src.format);
-        const size_t dbpr = dst.stride * bpp;
-        const size_t sbpr = src.stride * bpp;
-        while (iterator.iterate(&r)) {
-            ssize_t h = r.bottom - r.top;
-            if (h) {
-                size_t size = (r.right - r.left) * bpp;
-                uint8_t* s = src.data + (r.left + src.stride * r.top) * bpp;
-                uint8_t* d = dst.data + (r.left + dst.stride * r.top) * bpp;
-                if (dbpr==sbpr && size==sbpr) {
-                    size *= h;
-                    h = 1;
-                }
-                do {
-                    memcpy(d, s, size);
-                    d += dbpr;
-                    s += sbpr;
-                } while (--h > 0);
-            }
-        }
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-surface_flinger_cblk_t::surface_flinger_cblk_t()
-{
-}
-
-// ---------------------------------------------------------------------------
-
-per_client_cblk_t::per_client_cblk_t()
-{
-}
-
 // these functions are used by the clients
-inline status_t per_client_cblk_t::validate(size_t i) const {
+status_t per_client_cblk_t::validate(size_t i) const {
     if (uint32_t(i) >= NUM_LAYERS_MAX)
         return BAD_INDEX;
     if (layers[i].swapState & eInvalidSurface)
@@ -248,8 +200,9 @@
         index = (state&eIndex) ^ ((state&eFlipRequested)>>1);
 
 	    // make sure this buffer is valid
-	    if (layer->surface[index].bits_offset < 0) {
-	        return status_t(layer->surface[index].bits_offset);
+        status_t err = layer->surface[index].status;
+	    if (err < 0) {
+	        return err;
 	    }
 
         if (inspect) {
@@ -273,7 +226,7 @@
 
 uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
 {
-    // atomically set eFlipRequested and clear eLocked and optionnaly
+    // atomically set eFlipRequested and clear eLocked and optionally
     // set eNextFlipPending if eFlipRequested was already set
 
     layer_cblk_t * const layer = layers + i;
@@ -290,7 +243,7 @@
 
         if (oldvalue & eFlipRequested)
             newvalue |= eNextFlipPending;
-            // if eFlipRequested was alread set, set eNextFlipPending
+            // if eFlipRequested was already set, set eNextFlipPending
 
     } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState)));
 
@@ -298,9 +251,9 @@
             int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift),
             int(newvalue));
 
-    // from this point, the server can kick in at anytime and use the first
+    // from this point, the server can kick in at any time and use the first
     // buffer, so we cannot use it anymore, and we must use the 'other'
-    // buffer instead (or wait if it is not availlable yet, see lock_layer).
+    // buffer instead (or wait if it is not available yet, see lock_layer).
 
     return newvalue;
 }
@@ -376,32 +329,6 @@
     return mStatus;
 }
 
-status_t SurfaceComposerClient::validateSurface(
-        per_client_cblk_t const* cblk, Surface const * surface)
-{
-    SurfaceID index = surface->ID();
-    if (cblk == 0) {
-        LOGE("cblk is null (surface id=%d, identity=%u)",
-                index, surface->getIdentity());
-        return NO_INIT;
-    }
-
-    status_t err = cblk->validate(index);
-    if (err != NO_ERROR) {
-        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
-                index, surface->getIdentity(), err, strerror(-err));
-        return err;
-    }
-
-    if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) {
-        LOGE("using an invalid surface id=%d, identity=%u should be %d",
-                index, surface->getIdentity(), cblk->layers[index].identity);
-        return NO_INIT;
-    }
-
-    return NO_ERROR;
-}
-
 sp<IBinder> SurfaceComposerClient::connection() const
 {
     return (mClient != 0) ? mClient->asBinder() : 0;
@@ -439,7 +366,6 @@
 
     sp<IMemory>                 controlMemory;
     sp<ISurfaceFlingerClient>   client;
-    sp<IMemoryHeap>             surfaceHeap;
 
     {
         Mutex::Autolock _lg(gLock);
@@ -462,9 +388,7 @@
         delete mPrebuiltLayerState;
         mPrebuiltLayerState = 0;
         controlMemory = mControlMemory;
-        surfaceHeap = mSurfaceHeap;
         mControlMemory.clear();
-        mSurfaceHeap.clear();
         mControl = 0;
         mStatus = NO_INIT;
     }
@@ -528,6 +452,12 @@
     return n;
 }
 
+
+void SurfaceComposerClient::signalServer()
+{
+    mSignalServer->signal();
+}
+
 sp<Surface> SurfaceComposerClient::createSurface(
         int pid,
         DisplayID display,
@@ -568,186 +498,6 @@
     return err;
 }
 
-status_t SurfaceComposerClient::nextBuffer(Surface* surface,
-                        Surface::SurfaceInfo* info)
-{
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface);
-    if (err != NO_ERROR)
-        return err;
-
-    int32_t backIdx = surface->mBackbufferIndex;
-    layer_cblk_t* const lcblk = &(cblk->layers[index]);
-    const surface_info_t* const front = lcblk->surface + (1-backIdx);
-        info->w      = front->w;
-        info->h      = front->h;
-        info->format = front->format;
-        info->base   = surface->heapBase(1-backIdx);
-        info->bits   = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset);
-        info->bpr    = front->bpr;
-
-    return 0;
-}
-
-status_t SurfaceComposerClient::lockSurface(
-        Surface* surface,
-        Surface::SurfaceInfo* other,
-        Region* dirty,
-        bool blocking)
-{
-    Mutex::Autolock _l(surface->getLock());
-
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface);
-    if (err != NO_ERROR)
-        return err;
-
-    int32_t backIdx = cblk->lock_layer(size_t(index),
-            per_client_cblk_t::BLOCKING);
-    if (backIdx >= 0) {
-        surface->mBackbufferIndex = backIdx;
-        layer_cblk_t* const lcblk = &(cblk->layers[index]);
-        const surface_info_t* const back = lcblk->surface + backIdx;
-        const surface_info_t* const front = lcblk->surface + (1-backIdx);
-            other->w      = back->w;
-            other->h      = back->h;
-            other->format = back->format;
-            other->base   = surface->heapBase(backIdx);
-            other->bits   = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset);
-            other->bpr    = back->bpr;
-
-        const Rect bounds(other->w, other->h);
-        Region newDirtyRegion;
-
-        if (back->flags & surface_info_t::eBufferDirty) {
-            /* it is safe to write *back here, because we're guaranteed
-             * SurfaceFlinger is not touching it (since it just granted
-             * access to us) */
-            const_cast<surface_info_t*>(back)->flags &=
-                    ~surface_info_t::eBufferDirty;
-
-            // content is meaningless in this case and the whole surface
-            // needs to be redrawn.
-
-            newDirtyRegion.set(bounds);
-            if (dirty) {
-                *dirty = newDirtyRegion;
-            }
-
-            //if (bytesPerPixel(other->format) == 4) {
-            //    android_memset32(
-            //        (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr);
-            //} else {
-            //    android_memset16( // fill with green
-            //        (uint16_t*)other->bits, 0x7E0, other->h * other->bpr);
-            //}
-        }
-        else
-        {
-            if (dirty) {
-                dirty->andSelf(Region(bounds));
-                newDirtyRegion = *dirty;
-            } else {
-                newDirtyRegion.set(bounds);
-            }
-
-            Region copyback;
-            if (!(lcblk->flags & eNoCopyBack)) {
-                const Region previousDirtyRegion(surface->dirtyRegion());
-                copyback = previousDirtyRegion.subtract(newDirtyRegion);
-            }
-
-            if (!copyback.isEmpty()) {
-                // copy front to back
-                GGLSurface cb;
-                    cb.version = sizeof(GGLSurface);
-                    cb.width = back->w;
-                    cb.height = back->h;
-                    cb.stride = back->stride;
-                    cb.data = (GGLubyte*)surface->heapBase(backIdx);
-                    cb.data += back->bits_offset;
-                    cb.format = back->format;
-
-                GGLSurface t;
-                    t.version = sizeof(GGLSurface);
-                    t.width = front->w;
-                    t.height = front->h;
-                    t.stride = front->stride;
-                    t.data = (GGLubyte*)surface->heapBase(1-backIdx);
-                    t.data += front->bits_offset;
-                    t.format = front->format;
-
-                //const Region copyback(lcblk->region + 1-backIdx);
-                copyBlt(cb, t, copyback);
-            }
-        }
-
-        // update dirty region
-        surface->setDirtyRegion(newDirtyRegion);
-    }
-    return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR);
-}
-
-void SurfaceComposerClient::_signal_server()
-{
-    mSignalServer->signal();
-}
-
-void SurfaceComposerClient::_send_dirty_region(
-        layer_cblk_t* lcblk, const Region& dirty)
-{
-    const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
-    flat_region_t* flat_region = lcblk->region + index;
-    status_t err = dirty.write(flat_region, sizeof(flat_region_t));
-    if (err < NO_ERROR) {
-        // region doesn't fit, use the bounds
-        const Region reg(dirty.bounds());
-        reg.write(flat_region, sizeof(flat_region_t));
-    }
-}
-
-status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface)
-{
-    Mutex::Autolock _l(surface->getLock());
-
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface);
-    if (err != NO_ERROR)
-        return err;
-
-    Region dirty(surface->dirtyRegion());
-    const Rect& swapRect(surface->swapRectangle());
-    if (swapRect.isValid()) {
-        dirty.set(swapRect);
-    }
-
-    // transmit the dirty region
-    layer_cblk_t* const lcblk = &(cblk->layers[index]);
-    _send_dirty_region(lcblk, dirty);
-    uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
-    if (!(newstate & eNextFlipPending))
-        _signal_server();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::unlockSurface(Surface* surface)
-{
-    Mutex::Autolock _l(surface->getLock());
-
-    SurfaceID index = surface->ID();
-    per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface);
-    if (err != NO_ERROR)
-        return err;
-
-    layer_cblk_t* const lcblk = &(cblk->layers[index]);
-    cblk->unlock_layer(size_t(index));
-    return NO_ERROR;
-}
-
 void SurfaceComposerClient::openGlobalTransaction()
 {
     Mutex::Autolock _l(gLock);
@@ -870,7 +620,7 @@
 {
     SurfaceID index = surface->ID();
     per_client_cblk_t* const cblk = mControl;
-    status_t err = validateSurface(cblk, surface.get());
+    status_t err = surface->validate(cblk);
     if (err != NO_ERROR)
         return 0;
 
@@ -973,7 +723,6 @@
     return NO_ERROR;
 }
 
-
 status_t SurfaceComposerClient::setTransparentRegionHint(
         Surface* surface, const Region& transparentRegion)
 {