Code drop from //branches/cupcake/...@124589
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 7741456..d14cebf 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -31,6 +31,7 @@
 endif
 
 LOCAL_SHARED_LIBRARIES := \
+	libhardware \
 	libutils \
 	libcutils \
 	libui \
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 5dd9446..cd72179 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <math.h>
 
 #include <GLES/egl.h>
 
@@ -27,7 +28,9 @@
 #include <ui/EGLDisplaySurface.h>
 
 #include "DisplayHardware/DisplayHardware.h"
-#include "ui/BlitHardware.h"
+
+#include <hardware/copybit.h>
+#include <hardware/overlay.h>
 
 using namespace android;
 
@@ -91,19 +94,13 @@
     fini();
 }
 
-float DisplayHardware::getDpiX() const           { return mDpiX; }
-float DisplayHardware::getDpiY() const           { return mDpiY; }
-float DisplayHardware::getRefreshRate() const    { return mRefreshRate; }
-
-int DisplayHardware::getWidth() const {
-    return mWidth;
-}
-int DisplayHardware::getHeight() const {
-    return mHeight;
-}
-PixelFormat DisplayHardware::getFormat() const {
-    return mFormat;
-}
+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)
 {
@@ -195,6 +192,12 @@
         mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
     }
     mRefreshRate = 60.f;    // TODO: get the real refresh rate 
+    
+    // compute a "density" automatically as a scale factor from 160 dpi
+    // TODO: this value should be calculated a compile time based on the
+    // board.
+    mDensity = floorf((mDpiX>mDpiY ? mDpiX : mDpiY)*0.1f + 0.5f) * (10.0f/160.0f);
+    LOGI("density = %f", mDensity);
 
     /*
      * Create our OpenGL ES context
@@ -237,8 +240,18 @@
     mSurface = surface;
     mContext = context;
     mFormat  = GGL_PIXEL_FORMAT_RGB_565;
+    
+    hw_module_t const* module;
 
-    mBlitEngine = copybit_init();
+    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_open(module, &mOverlayEngine);
+    }
 }
 
 /*
@@ -252,7 +265,8 @@
 {
     eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(mDisplay);
-    copybit_term(mBlitEngine);
+    copybit_close(mBlitEngine);
+    overlay_close(mOverlayEngine);
 }
 
 void DisplayHardware::releaseScreen() const
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index 299e236..de4a2cc 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -26,6 +26,8 @@
 
 #include "DisplayHardware/DisplayHardwareBase.h"
 
+struct overlay_device_t;
+struct copybit_device_t;
 struct copybit_image_t;
 struct copybit_t;
 
@@ -64,6 +66,7 @@
     float       getDpiX() const;
     float       getDpiY() const;
     float       getRefreshRate() const;
+    float       getDensity() const;
     int         getWidth() const;
     int         getHeight() const;
     PixelFormat getFormat() const;
@@ -74,7 +77,8 @@
     void getDisplaySurface(copybit_image_t* img) const;
     void getDisplaySurface(GGLSurface* fb) const;
     EGLDisplay getEGLDisplay() const { return mDisplay; }
-    copybit_t* getBlitEngine() const { return mBlitEngine; }
+    copybit_device_t* getBlitEngine() const { return mBlitEngine; }
+    overlay_device_t* getOverlayEngine() const { return mOverlayEngine; }
     
     Rect bounds() const {
         return Rect(mWidth, mHeight);
@@ -91,13 +95,15 @@
     float           mDpiX;
     float           mDpiY;
     float           mRefreshRate;
+    float           mDensity;
     int             mWidth;
     int             mHeight;
     PixelFormat     mFormat;
     uint32_t        mFlags;
     mutable Region  mDirty;
     sp<EGLDisplaySurface> mDisplaySurface;
-    copybit_t*      mBlitEngine;
+    copybit_device_t*     mBlitEngine;
+    overlay_device_t*     mOverlayEngine;
 };
 
 }; // namespace android
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index 90f6287..f75e5c2 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -49,8 +49,10 @@
 // ----------------------------------------------------------------------------
 namespace android {
 
-static char const * const kSleepFileName = "/sys/android_power/wait_for_fb_sleep";
-static char const * const kWakeFileName = "/sys/android_power/wait_for_fb_wake";
+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.
@@ -123,16 +125,22 @@
 status_t DisplayHardwareBase::DisplayEventThread::readyToRun()
 {
     if (access(kSleepFileName, R_OK) || access(kWakeFileName, R_OK)) {
-        LOGE("Couldn't open %s or %s", kSleepFileName, kWakeFileName);
-        return NO_INIT;
+        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 &&
+    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;
 }
 
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
index b24a0f2..eb75f99 100644
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
@@ -30,6 +30,7 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
+#include <utils/IBinder.h>
 #include <utils/MemoryDealer.h>
 #include <utils/MemoryBase.h>
 #include <utils/MemoryHeapPmem.h>
@@ -48,36 +49,113 @@
 
 #include "GPUHardware/GPUHardware.h"
 
+
 /* 
- * This file manages the GPU if there is one. The intent is that this code
- * needs to be different for every devce. Currently there is no abstraction,
- * but in the long term, this code needs to be refactored so that API and
- * implementation are separated.
+ * Manage the GPU. This implementation is very specific to the G1.
+ * There are no abstraction here. 
  * 
- * In this particular implementation, the GPU, its memory and register are
- * managed here. Clients (such as OpenGL ES) request the GPU when then need
- * it and are given a revokable heap containing the registers on memory. 
+ * 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-bufferd, 4x anti-aliased surface
-static const int GPU_RESERVED_SIZE  = 1200 * 1024;
-
-static const int GPUR_SIZE          = 1 * 1024 * 1024;
+//  - 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 explicitely revoke their acces through the binder code 1000.
+ * 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.
  * 
@@ -92,42 +170,99 @@
  * 
  */
 
-class GPUHandle : public BnMemory
+class GPUClientHeap : public MemoryHeapPmem
 {
 public:
-            GPUHandle(const sp<GPUHardware>& gpu, const sp<IMemoryHeap>& heap)
-                : mGPU(gpu), mClientHeap(heap) {
-            }
-    virtual ~GPUHandle();
-    virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
-    virtual status_t onTransact(
-            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
-    void setOwner(int owner) { mOwner = owner; }
-private:
-    void revokeNotification();
+    GPUClientHeap(const wp<GPUHardware>& gpu, 
+            const sp<MemoryHeapBase>& heap)
+        :  MemoryHeapPmem(heap), mGPU(gpu) { }
+protected:
     wp<GPUHardware> mGPU;
-    sp<IMemoryHeap> mClientHeap;
-    int mOwner;
 };
 
-GPUHandle::~GPUHandle() { 
+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 GPUHandle::revokeNotification()  {
+void GPURegisterHeap::MemoryHeapRegs::GPUHandle::revokeNotification()  {
     sp<GPUHardware> hw(mGPU.promote());
     if (hw != 0) {
         hw->revoke(mOwner);
     }
 }
-sp<IMemoryHeap> GPUHandle::getMemory(ssize_t* offset, size_t* size) const
+sp<IMemoryHeap> GPURegisterHeap::MemoryHeapRegs::GPUHandle::getMemory(
+        ssize_t* offset, size_t* size) const
 {
+    sp<MemoryHeapPmem> heap = getHeap();
     if (offset) *offset = 0;
-    if (size)   *size = mClientHeap !=0 ? mClientHeap->virtualSize() : 0;
-    return mClientHeap;
+    if (size)   *size = heap !=0 ? heap->virtualSize() : 0;
+    return heap;
 }
-status_t GPUHandle::onTransact(
+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);
@@ -150,22 +285,14 @@
 
 // ---------------------------------------------------------------------------
 
-class MemoryHeapRegs : public MemoryHeapPmem 
-{
-public:
-            MemoryHeapRegs(const wp<GPUHardware>& gpu, const sp<MemoryHeapBase>& heap);
-    virtual ~MemoryHeapRegs();
-    sp<IMemory> mapMemory(size_t offset, size_t size);
-    virtual void revoke();
-private:
-    wp<GPUHardware> mGPU;
-};
 
-MemoryHeapRegs::MemoryHeapRegs(const wp<GPUHardware>& gpu, const sp<MemoryHeapBase>& heap)
-    :  MemoryHeapPmem(heap), mGPU(gpu)
+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
-    if (heapID()>0) {
         /* this is where the GPU is powered on and the registers are mapped
          * in the client */
         //LOGD("ioctl(HW3D_GRANT_GPU)");
@@ -174,27 +301,16 @@
             // 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());
+            LOGW("HW3D_GRANT_GPU failed (%s), mFD=%d, base=%p",
+                    strerror(errno), heapID(), base());
         }
-    }
-#endif
-}
-
-MemoryHeapRegs::~MemoryHeapRegs() 
-{
-}
-
-sp<IMemory> MemoryHeapRegs::mapMemory(size_t offset, size_t size)
-{
-    sp<GPUHandle> memory;
-    sp<GPUHardware> gpu = mGPU.promote();
-    if (heapID()>0 && gpu!=0) 
         memory = new GPUHandle(gpu, this);
+#endif
+    }
     return memory;
 }
 
-void MemoryHeapRegs::revoke() 
+void GPURegisterHeap::MemoryHeapRegs::revoke() 
 {
     MemoryHeapPmem::revoke();
 #if HAVE_ANDROID_OS
@@ -207,25 +323,6 @@
 #endif
 }
 
-// ---------------------------------------------------------------------------
-
-class GPURegisterHeap : public PMemHeapInterface
-{
-public:
-    GPURegisterHeap(const sp<GPUHardware>& gpu)
-        : PMemHeapInterface("/dev/hw3d", GPUR_SIZE), mGPU(gpu)
-    {
-    }
-    virtual ~GPURegisterHeap() {
-    }
-    virtual sp<MemoryHeapPmem> createClientHeap() {
-        sp<MemoryHeapBase> parentHeap(this);
-        return new MemoryHeapRegs(mGPU, parentHeap);
-    }
-private:
-    wp<GPUHardware> mGPU;
-};
-
 /*****************************************************************************/
 
 GPUHardware::GPUHardware()
@@ -237,85 +334,87 @@
 {
 }
 
-sp<MemoryDealer> GPUHardware::request(int pid)
+status_t GPUHardware::requestLocked(int pid)
 {
-    sp<MemoryDealer> dealer;
-
-    LOGD("pid %d requesting gpu surface (current owner = %d)", pid, mOwner);
-
     const int self_pid = getpid();
     if (pid == self_pid) {
         // can't use GPU from surfaceflinger's process
-        return dealer;
-    }
-
-    Mutex::Autolock _l(mLock);
-    
-    if (mOwner != pid) {
-        // someone already has the gpu.
-        takeBackGPULocked();
-
-        // releaseLocked() should be a no-op most of the time
-        releaseLocked();
-
-        requestLocked(); 
-    }
-
-    dealer = mAllocator;
-    mOwner = pid;
-    if (dealer == 0) {
-        mOwner = SURFACE_FAILED;
-    }
-    
-    LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner);
-    return dealer;
-}
-
-status_t GPUHardware::request(const sp<IGPUCallback>& callback,
-        ISurfaceComposer::gpu_info_t* gpu)
-{
-    sp<IMemory> gpuHandle;
-    IPCThreadState* ipc = IPCThreadState::self();
-    const int pid = ipc->getCallingPid();
-    const int self_pid = getpid();
-
-    LOGD("pid %d requesting gpu core (owner = %d)", pid, mOwner);
-
-    if (pid == self_pid) {
-        // can't use GPU from surfaceflinger's process
         return PERMISSION_DENIED;
     }
 
-    Mutex::Autolock _l(mLock);
     if (mOwner != pid) {
-        // someone already has the gpu.
-        takeBackGPULocked();
-
-        // releaseLocked() should be a no-op most of the time
-        releaseLocked();
-
-        requestLocked(); 
+        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;
+}
 
-    if (mHeapR.isValid()) {
+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 = mHeap0.map(true);
-        gpu->regions[0].reserved = mHeap0.reserved;
-        gpu->regions[1].region = mHeap1.map(true);
-        gpu->regions[1].reserved = mHeap1.reserved;
-        gpu->regs = mHeapR.map();
+        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) {
-            static_cast< GPUHandle* >(gpu->regs.get())->setOwner(pid);
+            //LOGD("gpu core granted to pid %d, handle base=%p",
+            //        mOwner, gpu->regs->pointer());
         }
         mCallback = callback;
-        mOwner = pid;
-        //LOGD("gpu core granted to pid %d, handle base=%p",
-        //        mOwner, gpu->regs->pointer());
     } else {
         LOGW("couldn't grant gpu core to pid %d", pid);
     }
-
-    return NO_ERROR;
+    return err;
 }
 
 void GPUHardware::revoke(int pid)
@@ -330,16 +429,16 @@
         // mOwner could be <0 if the same process acquired the GPU
         // several times without releasing it first.
         mCondition.signal();
-        releaseLocked(true);
+        releaseLocked();
     }
 }
 
 status_t GPUHardware::friendlyRevoke()
 {
     Mutex::Autolock _l(mLock);
-    takeBackGPULocked();
     //LOGD("friendlyRevoke owner=%d", mOwner);
-    releaseLocked(true);
+    takeBackGPULocked();
+    releaseLocked();
     return NO_ERROR;
 }
 
@@ -353,90 +452,37 @@
     }
 }
 
-void GPUHardware::requestLocked()
+void GPUHardware::releaseLocked()
 {
-    if (mAllocator == 0) {
-        GPUPart* part = 0;
-        sp<PMemHeap> surfaceHeap;
-        if (mHeap1.promote() == false) {
-            //LOGD("requestLocked: (1) creating new heap");
-            mHeap1.set(new PMemHeap("/dev/pmem_gpu1", 0, GPU_RESERVED_SIZE));
+    //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();
         }
-        if (mHeap1.isValid()) {
-            //LOGD("requestLocked: (1) heap is valid");
-            // NOTE: if GPU1 is available we use it for our surfaces
-            // this could be device specific, so we should do something more
-            // generic
-            surfaceHeap = static_cast< PMemHeap* >( mHeap1.getHeap().get() );
-            part = &mHeap1;
-            if (mHeap0.promote() == false) {
-                //LOGD("requestLocked: (0) creating new heap");
-                mHeap0.set(new PMemHeap("/dev/pmem_gpu0"));
-            }
-        } else {
-            //LOGD("requestLocked: (1) heap is not valid");
-            // No GPU1, use GPU0 only
-            if (mHeap0.promote() == false) {
-                //LOGD("requestLocked: (0) creating new heap");
-                mHeap0.set(new PMemHeap("/dev/pmem_gpu0", 0, GPU_RESERVED_SIZE));
-            }
-            if (mHeap0.isValid()) {
-                //LOGD("requestLocked: (0) heap is valid");
-                surfaceHeap = static_cast< PMemHeap* >( mHeap0.getHeap().get() );
-                part = &mHeap0;
-            }
-        }
-        
-        if (mHeap0.isValid() || mHeap1.isValid()) {
-            if (mHeapR.promote() == false) {
-                //LOGD("requestLocked: (R) creating new register heap");
-                mHeapR.set(new GPURegisterHeap(this));
-            }
-        } else {
-            // we got nothing...
-            mHeap0.clear();
-            mHeap1.clear();
-        }
-
-        if (mHeapR.isValid() == false) {
-            //LOGD("requestLocked: (R) register heap not valid!!!");
-            // damn, couldn't get the gpu registers!
-            mHeap0.clear();
-            mHeap1.clear();
-            surfaceHeap.clear();
-            part = NULL;
-        }
-
-        if (surfaceHeap != 0 && part && part->getClientHeap()!=0) {
-            part->reserved = GPU_RESERVED_SIZE;
-            part->surface = true;
-            mAllocatorDebug = static_cast<SimpleBestFitAllocator*>(
-                    surfaceHeap->getAllocator().get());
-            mAllocator = new MemoryDealer(
-                    part->getClientHeap(),
-                    surfaceHeap->getAllocator());
-        }
+        mOwner = NO_OWNER;
+        mCurrentAllocator.clear();
+        mCallback.clear();
     }
 }
 
-void GPUHardware::releaseLocked(bool dispose)
+GPUHardware::Client& GPUHardware::getClientLocked(pid_t pid)
 {
-    /* 
-     * if dispose is set, we will force the destruction of the heap,
-     * so it is given back to other systems, such as camera.
-     * Otherwise, we'll keep a weak pointer to it, this way we might be able
-     * to reuse it later if it's still around. 
-     */
-    //LOGD("revoking gpu from pid %d", mOwner);
-    mOwner = NO_OWNER;
-    mAllocator.clear();
-    mCallback.clear();
-
-    /* if we're asked for a full revoke, dispose only of the heap
-     * we're not using for surface (as we might need it while drawing) */
-    mHeap0.release(mHeap0.surface ? false : dispose);
-    mHeap1.release(mHeap1.surface ? false : dispose);
-    mHeapR.release(false);
+    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;
 }
 
 // ----------------------------------------------------------------------------
@@ -444,8 +490,7 @@
 
 sp<SimpleBestFitAllocator> GPUHardware::getAllocator() const {
     Mutex::Autolock _l(mLock);
-    sp<SimpleBestFitAllocator> allocator = mAllocatorDebug.promote();
-    return allocator;
+    return mAllocator;
 }
 
 void GPUHardware::unconditionalRevoke()
@@ -456,102 +501,81 @@
 
 // ---------------------------------------------------------------------------
 
-
-GPUHardware::GPUPart::GPUPart()
-    : surface(false), reserved(0)
-{
-}
-
-GPUHardware::GPUPart::~GPUPart() {
-}
-    
-const sp<PMemHeapInterface>& GPUHardware::GPUPart::getHeap() const {
-    return mHeap;
-}
-
-const sp<MemoryHeapPmem>& GPUHardware::GPUPart::getClientHeap() const {
-    return mClientHeap;
-}
-
-bool GPUHardware::GPUPart::isValid() const {
-    return ((mHeap!=0) && (mHeap->base() != MAP_FAILED));
-}
-
-void GPUHardware::GPUPart::clear() 
-{
-    mHeap.clear();
-    mHeapWeak.clear();
-    mClientHeap.clear();
-    surface = false;
-}
-
-void GPUHardware::GPUPart::set(const sp<PMemHeapInterface>& heap) 
-{
-    mHeapWeak.clear();
-    if (heap!=0 && heap->base() == MAP_FAILED) {
-        mHeap.clear();
-        mClientHeap.clear();
-    } else { 
-        mHeap = heap;
-        mClientHeap = mHeap->createClientHeap();
-    }
-}
-
-bool GPUHardware::GPUPart::promote() 
-{
-    //LOGD("mHeapWeak=%p, mHeap=%p", mHeapWeak.unsafe_get(), mHeap.get());
-    if (mHeap == 0) {
-        mHeap = mHeapWeak.promote();
-    }
-    if (mHeap != 0) {
-        if (mClientHeap != 0) {
-            mClientHeap->revoke();
-        }
-        mClientHeap = mHeap->createClientHeap();
-    }  else {
-        surface = false;
-    }
-    return mHeap != 0;
-}
-
-sp<IMemory> GPUHardware::GPUPart::map(bool clear) 
-{
+sp<IMemory> GPUHardware::GPUArea::map() {
     sp<IMemory> memory;
-    if (mClientHeap != NULL) {
-        memory = mClientHeap->mapMemory(0, mHeap->virtualSize());
-        if (clear && memory!=0) {
-            //StopWatch sw("memset");
-            memset(memory->pointer(), 0, memory->size());
-        }
+    if (clientHeap != 0 && heap != 0) {
+        memory = clientHeap->mapMemory(0, heap->virtualSize());
     }
     return memory;
 }
 
-void GPUHardware::GPUPart::release(bool dispose)
+void GPUHardware::Client::createClientHeaps() 
 {
-    if (mClientHeap != 0) {
-        mClientHeap->revoke();
-        mClientHeap.clear();
+    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);
     }
-    if (dispose) {
-        if (mHeapWeak!=0 && mHeap==0) {
-            mHeap = mHeapWeak.promote();
-        }
-        if (mHeap != 0) {
-            mHeap->dispose();
-            mHeapWeak.clear();
-            mHeap.clear();
-        } else {
-            surface = false;
-        }
-    } else {
-        if (mHeap != 0) {
-            mHeapWeak = mHeap;
-            mHeap.clear();
+}
+
+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
index 9a78b99..3354528 100644
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.h
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.h
@@ -22,92 +22,39 @@
 
 #include <utils/RefBase.h>
 #include <utils/threads.h>
+#include <utils/KeyedVector.h>
+
+#include <ui/ISurfaceComposer.h>
 
 namespace android {
 
 // ---------------------------------------------------------------------------
 
-class GPUHardwareInterface : public RefBase
+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(const sp<IGPUCallback>& callback,
+    virtual status_t            request(int pid, const sp<IGPUCallback>& callback,
             ISurfaceComposer::gpu_info_t* gpu) = 0;
 
     virtual status_t            friendlyRevoke() = 0;
-    virtual void                unconditionalRevoke() = 0;
     
     // used for debugging only...
     virtual sp<SimpleBestFitAllocator> getAllocator() const  = 0;
     virtual pid_t getOwner() const = 0;
+    virtual void unconditionalRevoke() = 0;
 };
 
 // ---------------------------------------------------------------------------
 
-class IMemory;
-class MemoryHeapPmem;
-class PMemHeap;
-
-class GPUHardware : public GPUHardwareInterface
-{
+class GPUFactory
+{    
 public:
-            GPUHardware();
-    virtual ~GPUHardware();
-    
-    virtual void                revoke(int pid);
-    virtual sp<MemoryDealer>    request(int pid);
-    virtual status_t            request(const sp<IGPUCallback>& callback,
-            ISurfaceComposer::gpu_info_t* gpu);
-
-    virtual status_t            friendlyRevoke();
-    virtual void                unconditionalRevoke();
-    
-    // used for debugging only...
-    virtual sp<SimpleBestFitAllocator> getAllocator() const;
-    virtual pid_t getOwner() const { return mOwner; }
-    
-private:
-    enum {
-        NO_OWNER        = -1,
-        SURFACE_FAILED  = -2
-    };
-    
-    void requestLocked();
-    void releaseLocked(bool dispose = false);
-    void takeBackGPULocked();
-    
-    class GPUPart
-    {
-    public:
-        bool surface;
-        size_t reserved;
-        GPUPart();
-        ~GPUPart();
-        const sp<PMemHeapInterface>& getHeap() const;
-        const sp<MemoryHeapPmem>& getClientHeap() const;
-        bool isValid() const;
-        void clear();
-        void set(const sp<PMemHeapInterface>& heap);
-        bool promote();
-        sp<IMemory> map(bool clear = false);
-        void release(bool dispose);
-    private:
-        sp<PMemHeapInterface>   mHeap;
-        wp<PMemHeapInterface>   mHeapWeak;
-        sp<MemoryHeapPmem>      mClientHeap;
-    };
-    
-    mutable Mutex   mLock;
-    GPUPart         mHeap0; // SMI
-    GPUPart         mHeap1; // EBI1
-    GPUPart         mHeapR;
-    sp<MemoryDealer> mAllocator;
-    pid_t            mOwner;
-    sp<IGPUCallback> mCallback;
-    wp<SimpleBestFitAllocator> mAllocatorDebug;
-    
-    Condition       mCondition;
+    // the gpu factory
+    static sp<GPUHardwareInterface> getGPU();
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 4f6bae1..8ba0851 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -92,26 +92,29 @@
     status_t err = getPixelFormatInfo(format, &info);
     if (err) return err;
 
-    // TODO: if eHardware is explicitely requested, we should fail
+    // 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;
 
-    int memory_type = NATIVE_MEMORY_TYPE_PMEM;
+    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;
 
-    const uint32_t mask = ISurfaceComposer::eGPU | ISurfaceComposer::eSecure;
-    if ((flags & mask) == 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::eHardware;
-            memory_type = NATIVE_MEMORY_TYPE_GPU;
-            // TODO: this value should come from the h/w
-            alignment = 8; 
+    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;
         }
     }
 
@@ -119,7 +122,7 @@
     mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
     sp<MemoryDealer> allocators[2];
     for (int i=0 ; i<2 ; i++) {
-        allocators[i] = client->createAllocator(memory_type);
+        allocators[i] = client->createAllocator(memory_flags);
         if (allocators[i] == 0)
             return NO_MEMORY;
         mBuffers[i].init(allocators[i]);
@@ -133,7 +136,7 @@
     mSurface = new Surface(clientIndex(),
             allocators[0]->getMemoryHeap(),
             allocators[1]->getMemoryHeap(),
-            memory_type, mIdentity);
+            mIdentity);
 
     return NO_ERROR;
 }
@@ -180,7 +183,7 @@
         front.getBitmapSurface(&src);
         copybit_rect_t srect = { 0, 0, t.width, t.height };
 
-        copybit_t* copybit = mFlinger->getBlitEngine();
+        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,
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 17c9f42..af353e2 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -30,7 +30,7 @@
 #include "DisplayHardware/DisplayHardware.h"
 
 
-// We don't honor the premultipliad alpha flags, which means that
+// 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
@@ -256,7 +256,7 @@
 
     // see if we can/should use 2D h/w with the new configuration
     mCanUseCopyBit = false;
-    copybit_t* copybit = mFlinger->getBlitEngine();
+    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);
@@ -413,7 +413,7 @@
         // premultiplied alpha.
         
         // If the texture doesn't have an alpha channel we can
-        // use REPLACE and switch to non premultiplied-alpha
+        // use REPLACE and switch to non premultiplied alpha
         // blending (SRCA/ONE_MINUS_SRCA).
         
         GLenum env, src;
@@ -431,11 +431,11 @@
         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);
-            glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
         } else {
             glDisable(GL_BLEND);
         }
@@ -463,7 +463,7 @@
             glMatrixMode(GL_TEXTURE);
             glLoadIdentity();
             if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
-                // find the smalest power-of-two that will accomodate our surface
+                // 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;
@@ -556,7 +556,7 @@
     GLuint texture_w = tw;
     GLuint texture_h = th;
     if (!(flags & DisplayHardware::NPOT_EXTENSION)) {
-        // find the smalest power-of-two that will accomodate our surface
+        // 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;
@@ -582,6 +582,8 @@
             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;
@@ -592,7 +594,7 @@
 regular:
         Rect bounds(dirty.bounds());
         GLvoid* data = 0;
-        if (texture_w!=textureWidth || texture_w!=textureHeight) {
+        if (texture_w!=textureWidth || texture_h!=textureHeight) {
             // texture size changed, we need to create a new one
 
             if (!textureWidth || !textureHeight) {
@@ -606,31 +608,36 @@
                     bounds.set(Rect(tw, th));
                 }
             }
-
+            
             if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
                 glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_RGB, tw, th, 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, tw, th, 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, tw, th, 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, tw, th, 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 = tw;
-            textureHeight = th;
+            textureWidth = texture_w;
+            textureHeight = texture_h;
         }
-        if (!data) {
+        if (!data && textureName>=0) {
             if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
                 glTexSubImage2D(GL_TEXTURE_2D, 0,
                         0, bounds.top, t.width, bounds.height(),
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 10c1bc1..b3f3771 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -23,6 +23,8 @@
 #include <private/ui/LayerState.h>
 
 #include <ui/Region.h>
+#include <ui/Overlay.h>
+
 #include <pixelflinger/pixelflinger.h>
 
 #include "Transform.h"
@@ -223,16 +225,14 @@
         Surface(SurfaceID id, int identity) { 
             mParams.token = id;
             mParams.identity = identity;
-            mParams.type = 0;
         }
         Surface(SurfaceID id, 
                 const sp<IMemoryHeap>& heap0,
                 const sp<IMemoryHeap>& heap1,
-                int memory_type, int identity)
+                int identity)
         {
             mParams.token = id;
             mParams.identity = identity;
-            mParams.type = memory_type;
             mParams.heap[0] = heap0;
             mParams.heap[1] = heap1;
         }
@@ -240,8 +240,8 @@
             // 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}, type=%d destroyed",
-            //        mId, mHeap[0].get(), mHeap[1].get(), mMemoryType);
+            //LOGD("Surface %d, heaps={%p, %p} destroyed",
+            //        mId, mHeap[0].get(), mHeap[1].get());
         }
 
         virtual void getSurfaceData(
@@ -254,6 +254,10 @@
                 { return INVALID_OPERATION; }
         virtual void postBuffer(ssize_t offset) { }
         virtual void unregisterBuffers() { };
+        virtual sp<Overlay> createOverlay(
+                uint32_t w, uint32_t h, int32_t format) {
+            return NULL;
+        };
 
     private:
         ISurfaceFlingerClient::surface_data_t mParams;
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 192ceda..e3ae7fb 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -145,11 +145,13 @@
             mRefreshCache = false;
             mAutoRefreshPending = false;
             
-            uint16_t* const pixels = (uint16_t*)malloc(w*h*2);
+            // 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
+            // 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.
+            // 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.
@@ -157,7 +159,7 @@
             bl.version = sizeof(GGLSurface);
             bl.width = w;
             bl.height = h;
-            bl.stride = w;
+            bl.stride = s;
             bl.format = GGL_PIXEL_FORMAT_RGB_565;
             bl.data = (GGLubyte*)pixels;            
             blurFilter(&bl, 8, 2);
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index d871fc3..3861e681 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -104,7 +104,7 @@
          * the requested scale factor, in which case we perform the scaling
          * in several passes. */
 
-        copybit_t* copybit = mFlinger->getBlitEngine();
+        copybit_device_t* copybit = mFlinger->getBlitEngine();
         const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
         const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
 
@@ -123,7 +123,7 @@
             if (UNLIKELY(mTemporaryDealer == 0)) {
                 // allocate a memory-dealer for this the first time
                 mTemporaryDealer = mFlinger->getSurfaceHeapManager()
-                        ->createHeap(NATIVE_MEMORY_TYPE_PMEM);
+                        ->createHeap(ISurfaceComposer::eHardware);
                 mTempBitmap.init(mTemporaryDealer);
             }
 
@@ -230,7 +230,18 @@
 status_t LayerBuffer::registerBuffers(int w, int h, int hstride, int vstride,
             PixelFormat format, const sp<IMemoryHeap>& memoryHeap)
 {
-    status_t err = (memoryHeap!=0 && memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT;
+    if (memoryHeap == NULL) {
+        // this is allowed, but in this case, it is illegal to receive
+        // postBuffer(). The surface just erases the framebuffer with
+        // fully transparent pixels.
+        mHeap.clear();
+        mWidth = w;
+        mHeight = h;
+        mNeedsBlending = false;
+        return NO_ERROR;
+    }
+    
+    status_t err = (memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT;
     if (err != NO_ERROR)
         return err;
 
@@ -281,6 +292,32 @@
     invalidateLocked();
 }
 
+sp<Overlay> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t format)
+{
+    sp<Overlay> result;
+    Mutex::Autolock _l(mLock);
+    if (mHeap != 0 || mBuffer != 0) {
+        // we're a push surface. error.
+        return result;
+    }
+    
+    overlay_device_t* overlay_dev = mFlinger->getOverlayEngine();
+    if (overlay_dev == NULL) {
+        // overlays not supported
+        return result;
+    }
+
+    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 result;
+    }
+    
+    /* TODO: implement the real stuff here */
+    
+    return result;
+}
+
 sp<LayerBuffer::Buffer> LayerBuffer::getBuffer() const
 {
     Mutex::Autolock _l(mLock);
@@ -330,6 +367,15 @@
         owner->unregisterBuffers();
 }
 
+sp<Overlay> LayerBuffer::SurfaceBuffer::createOverlay(
+        uint32_t w, uint32_t h, int32_t format) {
+    sp<Overlay> result;
+    LayerBuffer* owner(getOwner());
+    if (owner)
+        result = owner->createOverlay(w, h, format);
+    return result;
+}
+
 void LayerBuffer::SurfaceBuffer::disown()
 {
     Mutex::Autolock _l(mLock);
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index ef473dd..3e616f27 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -33,6 +33,7 @@
 
 class MemoryDealer;
 class Region;
+class Overlay;
 
 class LayerBuffer : public LayerBaseClient
 {
@@ -56,6 +57,7 @@
             PixelFormat format, const sp<IMemoryHeap>& heap);
     void postBuffer(ssize_t offset);
     void unregisterBuffers();
+    sp<Overlay> createOverlay(uint32_t w, uint32_t h, int32_t format);
     void invalidate();
     void invalidateLocked();
 
@@ -107,7 +109,9 @@
                 PixelFormat format, const sp<IMemoryHeap>& heap);
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
-        void disown();
+        virtual sp<Overlay> createOverlay(
+                uint32_t w, uint32_t h, int32_t format);
+       void disown();
     private:
         LayerBuffer* getOwner() const {
             Mutex::Autolock _l(mLock);
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index fc23d53..0c347cc 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -48,7 +48,7 @@
 {
     // must only be called once.
     mDimmerDealer = flinger->getSurfaceHeapManager()
-            ->createHeap(NATIVE_MEMORY_TYPE_PMEM);
+            ->createHeap(ISurfaceComposer::eHardware);
     if (mDimmerDealer != 0) {
         mDimmerBitmap.init(mDimmerDealer);
         mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565);
@@ -81,7 +81,7 @@
             mDimmerBitmap.getBitmapSurface(&src);
             const copybit_rect_t& srect(drect);
 
-            copybit_t* copybit = mFlinger->getBlitEngine();
+            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);
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 45496b2..e8de21a3 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -38,7 +38,6 @@
 #include <utils/String16.h>
 #include <utils/StopWatch.h>
 
-#include <ui/BlitHardware.h>
 #include <ui/PixelFormat.h>
 #include <ui/DisplayInfo.h>
 #include <ui/EGLDisplaySurface.h>
@@ -202,23 +201,6 @@
 {
     LOGI("SurfaceFlinger is starting");
 
-    // 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;
-
-    // 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(8 << 20);
-    mGPU = new GPUHardware();
-
     // debugging stuff...
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sf.showupdates", value, "0");
@@ -244,11 +226,16 @@
     glDeleteTextures(1, &mWormholeTexName);
 }
 
-copybit_t* SurfaceFlinger::getBlitEngine() const
+copybit_device_t* SurfaceFlinger::getBlitEngine() const
 {
     return graphicPlane(0).displayHardware().getBlitEngine();
 }
 
+overlay_device_t* SurfaceFlinger::getOverlayEngine() const
+{
+    return graphicPlane(0).displayHardware().getOverlayEngine();
+}
+
 sp<IMemory> SurfaceFlinger::getCblk() const
 {
     return mServerCblkMemory;
@@ -257,7 +244,9 @@
 status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback,
         gpu_info_t* gpu)
 {
-    status_t err = mGPU->request(callback, gpu);
+    IPCThreadState* ipc = IPCThreadState::self();
+    const int pid = ipc->getCallingPid();
+    status_t err = mGPU->request(pid, callback, gpu);
     return err;
 }
 
@@ -360,7 +349,26 @@
     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
@@ -395,7 +403,7 @@
     dcblk->xdpi         = hw.getDpiX();
     dcblk->ydpi         = hw.getDpiY();
     dcblk->fps          = hw.getRefreshRate();
-    dcblk->density      = 1.0f; // XXX: do someting more real here...
+    dcblk->density      = hw.getDensity();
     asm volatile ("":::"memory");
 
     // Initialize OpenGL|ES
@@ -407,6 +415,7 @@
     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);
@@ -1679,7 +1688,7 @@
 Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
     : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
 {
-    mSharedHeapAllocator = getSurfaceHeapManager()->createHeap(NATIVE_MEMORY_TYPE_HEAP);
+    mSharedHeapAllocator = getSurfaceHeapManager()->createHeap();
     const int pgsize = getpagesize();
     const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
     mCblkHeap = new MemoryDealer(cblksize);
@@ -1703,10 +1712,6 @@
     return mFlinger->getSurfaceHeapManager();
 }
 
-const sp<GPUHardwareInterface>& Client::getGPU() const {
-    return mFlinger->getGPU();
-}
-
 int32_t Client::generateId(int pid)
 {
     const uint32_t i = clz( ~mBitmap );
@@ -1734,25 +1739,11 @@
     }
 }
 
-sp<MemoryDealer> Client::createAllocator(int memory_type)
+sp<MemoryDealer> Client::createAllocator(uint32_t flags)
 {
     sp<MemoryDealer> allocator;
-    if (memory_type == NATIVE_MEMORY_TYPE_GPU) {
-        allocator = getGPU()->request(getClientPid());
-        if (allocator == 0)
-            memory_type = NATIVE_MEMORY_TYPE_PMEM;
-    }
-    if (memory_type == NATIVE_MEMORY_TYPE_PMEM) {
-        allocator = mPMemAllocator;
-        if (allocator == 0) {
-            allocator = getSurfaceHeapManager()->createHeap(
-                    NATIVE_MEMORY_TYPE_PMEM);
-            mPMemAllocator = allocator;
-        }
-    }
-    if (allocator == 0)
-        allocator = mSharedHeapAllocator;
-
+    allocator = getSurfaceHeapManager()->createHeap(
+            flags, getClientPid(), mSharedHeapAllocator);
     return allocator;
 }
 
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 1581474..92021d0 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -41,7 +41,8 @@
 #include "BootAnimation.h"
 #include "Barrier.h"
 
-struct copybit_t;
+struct copybit_device_t;
+struct overlay_device_t;
 
 namespace android {
 
@@ -74,7 +75,7 @@
             int32_t                 generateId(int pid);
             void                    free(int32_t id);
             status_t                bindLayer(LayerBaseClient* layer, int32_t id);
-            sp<MemoryDealer>        createAllocator(int memory_type);
+            sp<MemoryDealer>        createAllocator(uint32_t memory_type);
 
     inline  bool                    isValid(int32_t i) const;
     inline  const uint8_t*          inUseArray() const;
@@ -92,7 +93,6 @@
     
 private:
     int                     getClientPid() const { return mPid; }
-    const sp<GPUHardwareInterface>&  getGPU() const;
         
     int                         mPid;
     uint32_t                    mBitmap;
@@ -179,7 +179,8 @@
                 return mGPU; 
             }
 
-            copybit_t* getBlitEngine() const;
+            copybit_device_t* getBlitEngine() const;
+            overlay_device_t* getOverlayEngine() const;
             
 private:
     friend class BClient;
diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp
index 3852d51..77bc576 100644
--- a/libs/surfaceflinger/VRamHeap.cpp
+++ b/libs/surfaceflinger/VRamHeap.cpp
@@ -37,6 +37,8 @@
 
 #include <GLES/eglnatives.h>
 
+#include "GPUHardware/GPUHardware.h"
+#include "SurfaceFlinger.h"
 #include "VRamHeap.h"
 
 #if HAVE_ANDROID_OS
@@ -59,8 +61,9 @@
 
 // ---------------------------------------------------------------------------
 
-SurfaceHeapManager::SurfaceHeapManager(size_t clientHeapSize)
-    : mClientHeapSize(clientHeapSize)
+SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, 
+        size_t clientHeapSize)
+    : mFlinger(flinger), mClientHeapSize(clientHeapSize)
 {
     SurfaceHeapManager::global_pmem_heap = 1;
 }
@@ -81,25 +84,53 @@
     }
 }
 
-sp<MemoryDealer> SurfaceHeapManager::createHeap(int type)
+sp<MemoryDealer> SurfaceHeapManager::createHeap(
+        uint32_t flags,
+        pid_t client_pid,
+        const sp<MemoryDealer>& defaultAllocator)
 {
-    if (!global_pmem_heap && type==NATIVE_MEMORY_TYPE_PMEM)
-        type = NATIVE_MEMORY_TYPE_HEAP;
-
-    const sp<PMemHeap>& heap(mPMemHeap);
     sp<MemoryDealer> dealer; 
-    switch (type) {
-    case NATIVE_MEMORY_TYPE_HEAP:
-        dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap");
-        break;
 
-    case NATIVE_MEMORY_TYPE_PMEM:
-        if (heap != 0) {
-            dealer = new MemoryDealer( 
-                    heap->createClientHeap(),
-                    heap->getAllocator());
+    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;
         }
-        break;
+    }
+
+    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;
 }
@@ -122,22 +153,8 @@
 
 // ---------------------------------------------------------------------------
 
-PMemHeapInterface::PMemHeapInterface(int fd, size_t size)
-    : MemoryHeapBase(fd, size) {
-}
-PMemHeapInterface::PMemHeapInterface(const char* device, size_t size)
-    : MemoryHeapBase(device, size) {
-}
-PMemHeapInterface::PMemHeapInterface(size_t size, uint32_t flags, char const * name)
-    : MemoryHeapBase(size, flags, name) {
-}
-PMemHeapInterface::~PMemHeapInterface() {
-}
-
-// ---------------------------------------------------------------------------
-
 PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved)
-    : PMemHeapInterface(device, size)
+    : MemoryHeapBase(device, size)
 {
     //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
     if (base() != MAP_FAILED) {
diff --git a/libs/surfaceflinger/VRamHeap.h b/libs/surfaceflinger/VRamHeap.h
index 03e0336..9140167 100644
--- a/libs/surfaceflinger/VRamHeap.h
+++ b/libs/surfaceflinger/VRamHeap.h
@@ -27,16 +27,19 @@
 
 class PMemHeap;
 class MemoryHeapPmem;
+class SurfaceFlinger; 
 
 // ---------------------------------------------------------------------------
 
 class SurfaceHeapManager  : public RefBase
 {
 public:
-    SurfaceHeapManager(size_t clientHeapSize);
+    SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize);
     virtual ~SurfaceHeapManager();
     virtual void onFirstRef();
-    sp<MemoryDealer> createHeap(int type);
+    /* 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;
@@ -44,6 +47,7 @@
 private:
     sp<PMemHeap> getHeap(int type) const;
 
+    sp<SurfaceFlinger> mFlinger;
     mutable Mutex   mLock;
     size_t          mClientHeapSize;
     sp<PMemHeap>    mPMemHeap;
@@ -52,19 +56,7 @@
 
 // ---------------------------------------------------------------------------
 
-class PMemHeapInterface : public MemoryHeapBase
-{
-public:
-    PMemHeapInterface(int fd, size_t size);
-    PMemHeapInterface(const char* device, size_t size = 0);
-    PMemHeapInterface(size_t size, uint32_t flags = 0, char const * name = NULL);
-    virtual ~PMemHeapInterface();
-    virtual sp<MemoryHeapPmem> createClientHeap() = 0;
-};
-
-// ---------------------------------------------------------------------------
-
-class PMemHeap : public PMemHeapInterface
+class PMemHeap : public MemoryHeapBase
 {
 public:
                 PMemHeap(const char* const vram,