hwc: hwc 1.1 implementation

Bug: 7124159

--External disabled
--MDP comp coded but disabled.
--Videos via overlay, so that secure videos can work.

Change-Id: Ie48b264143d5e4237ab9724e28930e3f68ba49ee
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 2142125..b5a1fdb 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -94,11 +94,6 @@
     }
 }
 
-int ExternalDisplay::getExternalDisplay() const {
-    Mutex::Autolock lock(mExtDispLock);
-    return mExternalDisplay;
-}
-
 ExternalDisplay::~ExternalDisplay()
 {
     closeFrameBuffer();
@@ -249,6 +244,9 @@
         if (mFd < 0)
             ALOGE("%s: /dev/graphics/fb1 not available", __FUNCTION__);
     }
+    if(mHwcContext) {
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].fd = mFd;
+    }
     return (mFd > 0);
 }
 
@@ -259,6 +257,9 @@
         ret = close(mFd);
         mFd = -1;
     }
+    if(mHwcContext) {
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].fd = mFd;
+    }
     return (ret == 0);
 }
 
@@ -411,11 +412,10 @@
             //Get the best mode and set
             // TODO: DO NOT call this for WFD
             setResolution(getBestMode());
+            setDpyAttr();
             //enable hdmi vsync
-            enableHDMIVsync(connected);
         } else {
             // Disable the hdmi vsync
-            enableHDMIVsync(connected);
             closeFrameBuffer();
             resetInfo();
         }
@@ -424,9 +424,9 @@
         const char* prop = (connected) ? "1" : "0";
         // set system property
         property_set("hw.hdmiON", prop);
-        /* Trigger redraw */
-        ALOGD_IF(DEBUG, "%s: Invalidate !!", __FUNCTION__);
-        ctx->proc->invalidate(ctx->proc);
+        //Inform SF
+        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
+        ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL, connected);
     }
     return;
 }
@@ -458,7 +458,7 @@
     return ret;
 }
 
-bool ExternalDisplay::commit()
+bool ExternalDisplay::post()
 {
     if(mFd == -1) {
         return false;
@@ -470,16 +470,73 @@
     return true;
 }
 
-int ExternalDisplay::enableHDMIVsync(int enable)
-{
-    if(mFd > 0) {
-        int ret = ioctl(mFd, MSMFB_OVERLAY_VSYNC_CTRL, &enable);
-        if (ret<0) {
-            ALOGE("%s: enabling HDMI vsync failed, str: %s", __FUNCTION__,
-                                                            strerror(errno));
-        }
+void ExternalDisplay::setDpyAttr() {
+    int width = 0, height = 0, fps = 0;
+    getAttrForMode(width, height, fps);
+    if(mHwcContext) {
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period = 1000000000l /
+        fps;
     }
-    return -errno;
+}
+
+void ExternalDisplay::getAttrForMode(int& width, int& height,
+int& fps) {
+    switch (mCurrentMode) {
+        case m640x480p60_4_3:
+            width = 640;
+            height = 480;
+            fps = 60;
+            break;
+        case m720x480p60_4_3:
+        case m720x480p60_16_9:
+            width = 720;
+            height = 480;
+            fps = 60;
+            break;
+        case m720x576p50_4_3:
+        case m720x576p50_16_9:
+            width = 720;
+            height = 576;
+            fps = 50;
+            break;
+        case m1280x720p50_16_9:
+            width = 1280;
+            height = 720;
+            fps = 50;
+            break;
+        case m1280x720p60_16_9:
+            width = 1280;
+            height = 720;
+            fps = 60;
+            break;
+        case m1920x1080p24_16_9:
+            width = 1920;
+            height = 1080;
+            fps = 24;
+            break;
+        case m1920x1080p25_16_9:
+            width = 1920;
+            height = 1080;
+            fps = 25;
+            break;
+        case m1920x1080p30_16_9:
+            width = 1920;
+            height = 1080;
+            fps = 30;
+            break;
+        case m1920x1080p50_16_9:
+            width = 1920;
+            height = 1080;
+            fps = 50;
+            break;
+        case m1920x1080p60_16_9:
+            width = 1920;
+            height = 1080;
+            fps = 60;
+            break;
+    }
 }
 
 };
diff --git a/libexternal/external.h b/libexternal/external.h
index 09cde3b..da3ccd5 100644
--- a/libexternal/external.h
+++ b/libexternal/external.h
@@ -30,27 +30,13 @@
 
 class ExternalDisplay
 {
-    //Type of external display -  OFF, HDMI, WFD
-    enum external_display_type {
-        EXT_TYPE_NONE,
-        EXT_TYPE_HDMI,
-        EXT_TYPE_WIFI
-    };
-
-    // Mirroring state
-    enum external_mirroring_state {
-        EXT_MIRRORING_OFF,
-        EXT_MIRRORING_ON,
-    };
 public:
     ExternalDisplay(hwc_context_t* ctx);
     ~ExternalDisplay();
     int getModeCount() const;
     void getEDIDModes(int *out) const;
-    int getExternalDisplay() const;
     void setExternalDisplay(int connected);
-    bool commit();
-    int enableHDMIVsync(int enable);
+    bool post();
     void setHPD(uint32_t startEnd);
     void setEDIDMode(int resMode);
     void setActionSafeDimension(int w, int h);
@@ -67,6 +53,8 @@
     int getModeOrder(int mode);
     int getBestMode();
     void resetInfo();
+    void setDpyAttr();
+    void getAttrForMode(int& width, int& height, int& fps);
 
     mutable android::Mutex mExtDispLock;
     int mFd;
diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp
index 022d658..0f67b14 100644
--- a/libgralloc/framebuffer.cpp
+++ b/libgralloc/framebuffer.cpp
@@ -100,51 +100,22 @@
 
 static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
 {
-    if (private_handle_t::validate(buffer) < 0)
-        return -EINVAL;
 
     fb_context_t* ctx = (fb_context_t*) dev;
 
     private_handle_t *hnd = static_cast<private_handle_t*>
-                            (const_cast<native_handle_t*>(buffer));
-
+            (const_cast<native_handle_t*>(buffer));
     private_module_t* m =
         reinterpret_cast<private_module_t*>(dev->common.module);
 
-
-    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
-        genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, GENLOCK_MAX_TIMEOUT);
-
-        if (m->currentBuffer) {
-            genlock_unlock_buffer(m->currentBuffer);
-            m->currentBuffer = 0;
-        }
-
-        const size_t offset = hnd->base - m->framebuffer->base;
-        // frame ready to be posted, signal so that hwc can update External
-        // display
-        pthread_mutex_lock(&m->fbPostLock);
-        m->currentOffset = offset;
-        m->fbPostDone = true;
-        pthread_cond_signal(&m->fbPostCond);
-        pthread_mutex_unlock(&m->fbPostLock);
-
-        m->info.activate = FB_ACTIVATE_VBL;
-        m->info.yoffset = offset / m->finfo.line_length;
+    if (hnd && hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+        m->info.activate = FB_ACTIVATE_VBL | FB_ACTIVATE_FORCE;
+        m->info.yoffset = hnd->offset / m->finfo.line_length;
         if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
-            ALOGE("FBIOPUT_VSCREENINFO failed");
-            genlock_unlock_buffer(hnd);
+            ALOGE("%s: FBIOPUT_VSCREENINFO failed for external, err: %s", __FUNCTION__,
+                    strerror(errno));
             return -errno;
         }
-
-        //Signals the composition thread to unblock and loop over if necessary
-        pthread_mutex_lock(&m->fbPanLock);
-        m->fbPanDone = true;
-        pthread_cond_signal(&m->fbPanCond);
-        pthread_mutex_unlock(&m->fbPanLock);
-
-        CALC_FPS();
-        m->currentBuffer = hnd;
     }
     return 0;
 }
@@ -387,7 +358,9 @@
 {
     fb_context_t* ctx = (fb_context_t*)dev;
     if (ctx) {
-        free(ctx);
+        //Hack until fbdev is removed. Framework could close this causing hwc a
+        //pain.
+        //free(ctx);
     }
     return 0;
 }
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 343686c..4e52ede 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -14,10 +14,7 @@
 LOCAL_SRC_FILES               := hwc.cpp          \
                                  hwc_video.cpp    \
                                  hwc_utils.cpp    \
-                                 hwc_uimirror.cpp \
                                  hwc_uevents.cpp  \
-                                 hwc_copybit.cpp  \
                                  hwc_mdpcomp.cpp  \
-                                 hwc_extonly.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index e688538..3be2def 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -26,13 +26,9 @@
 #include <fb_priv.h>
 #include <mdp_version.h>
 #include "hwc_utils.h"
-#include "hwc_qbuf.h"
 #include "hwc_video.h"
-#include "hwc_uimirror.h"
-#include "hwc_copybit.h"
 #include "external.h"
 #include "hwc_mdpcomp.h"
-#include "hwc_extonly.h"
 
 using namespace qhwc;
 
@@ -76,56 +72,66 @@
 }
 
 //Helper
-static void reset() {
-    //reset for this draw round
-    VideoOverlay::reset();
-    ExtOnly::reset();
-    UIMirrorOverlay::reset();
-    ExtOnly::reset();
-    //TODO MDPComp
+static void reset(hwc_context_t *ctx, int numDisplays) {
+    memset(ctx->listStats, 0, sizeof(ctx->listStats));
+    for(int i = 0; i < numDisplays; i++){
+        ctx->listStats[i].yuvIndex = -1;
+    }
+}
+
+static int hwc_prepare_primary(hwc_composer_device_1 *dev,
+        hwc_display_contents_1_t *list) {
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if (LIKELY(list && list->numHwLayers)) {
+        setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
+        if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY)) {
+            ctx->overlayInUse = true;
+        } else if(MDPComp::configure(ctx, list)) {
+            ctx->overlayInUse = true;
+        } else {
+            ctx->overlayInUse = false;
+        }
+    }
+    return 0;
+}
+
+static int hwc_prepare_external(hwc_composer_device_1 *dev,
+        hwc_display_contents_1_t *list) {
+
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if (LIKELY(list && list->numHwLayers)) {
+        setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
+        //Nothing to do for now
+    }
+    return 0;
 }
 
 static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
                        hwc_display_contents_1_t** displays)
 {
+    int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     ctx->overlayInUse = false;
 
-    reset();
+    reset(ctx, numDisplays);
 
     //If securing of h/w in progress skip comp using overlay.
     if(ctx->mSecuring == true) return 0;
 
     for (uint32_t i = 0; i < numDisplays; i++) {
         hwc_display_contents_1_t *list = displays[i];
-        //XXX: Actually handle the multiple displays
-        if (LIKELY(list && list->numHwLayers)) {
-            ctx->dpys[i] = list->dpy;
-
-            if(ctx->isPoweredDown)
-                ALOGW("SF called %s after a POWERDOWN", __FUNCTION__);
-
-            getLayerStats(ctx, list);
-            if(VideoOverlay::prepare(ctx, list)) {
-                ctx->overlayInUse = true;
-                //Nothing here
-            } else if(ExtOnly::prepare(ctx, list)) {
-                ctx->overlayInUse = true;
-            } else if(UIMirrorOverlay::prepare(ctx, list)) {
-                ctx->overlayInUse = true;
-            } else if(MDPComp::configure(dev, list)) {
-                ctx->overlayInUse = true;
-            } else if (0) {
-                //Other features
-                ctx->overlayInUse = true;
-            } else { // Else set this flag to false, otherwise video cases
-                // fail in non-overlay targets.
-                ctx->overlayInUse = false;
-            }
+        switch(i) {
+            case HWC_DISPLAY_PRIMARY:
+                ret = hwc_prepare_primary(dev, list);
+                break;
+            case HWC_DISPLAY_EXTERNAL:
+                ret = hwc_prepare_external(dev, list);
+                break;
+            default:
+                ret = -EINVAL;
         }
     }
-
-    return 0;
+    return ret;
 }
 
 static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
@@ -135,16 +141,15 @@
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     private_module_t* m = reinterpret_cast<private_module_t*>(
                 ctx->mFbDev->common.module);
-    //XXX: Handle dpy
     switch(event) {
         case HWC_EVENT_VSYNC:
-            if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0)
+            if(ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL,
+                    &enabled) < 0) {
+                ALOGE("%s: vsync control failed. Dpy=%d, enabled=%d : %s",
+                        __FUNCTION__, dpy, enabled, strerror(errno));
                 ret = -errno;
-
-            if(ctx->mExtDisplay->getExternalDisplay()) {
-                ret = ctx->mExtDisplay->enableHDMIVsync(enabled);
             }
-           break;
+            break;
         default:
             ret = -EINVAL;
     }
@@ -153,23 +158,37 @@
 
 static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
 {
-    //XXX: Handle based on dpy
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     private_module_t* m = reinterpret_cast<private_module_t*>(
         ctx->mFbDev->common.module);
-    if(blank) {
-        ctx->mOverlay->setState(ovutils::OV_CLOSED);
-        ctx->qbuf->unlockAllPrevious();
-        ALOGD("HWC Calling POWERDOWN ...");
-        ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
-        ALOGD("HWC Done POWERDOWN ...");
-        ctx->isPoweredDown = true;
-    } else {
-        ALOGD("HWC Calling UNBLANK ...");
-        ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
-        ALOGD("HWC Done UNBLANK ...");
-        ctx->isPoweredDown = false;
+    int ret = 0;
+    ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
+    switch(dpy) {
+        case HWC_DISPLAY_PRIMARY:
+            if(blank) {
+                ctx->mOverlay->setState(ovutils::OV_CLOSED);
+                ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
+            } else {
+                ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
+            }
+            break;
+        case HWC_DISPLAY_EXTERNAL:
+            if(blank) {
+                //TODO actual
+            } else {
+            }
+            break;
+        default:
+            return -EINVAL;
     }
+
+    if(ret < 0) {
+        ALOGE("%s: failed. Dpy=%d, blank=%d : %s",
+                __FUNCTION__, dpy, blank, strerror(errno));
+        return ret;
+    }
+    ALOGD("%s: Done Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
+    ctx->dpyAttr[dpy].isActive = !blank;
     return 0;
 }
 
@@ -179,16 +198,23 @@
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     private_module_t* m = reinterpret_cast<private_module_t*>(
         ctx->mFbDev->common.module);
+    int supported = HWC_DISPLAY_PRIMARY_BIT;
 
     switch (param) {
     case HWC_BACKGROUND_LAYER_SUPPORTED:
         // Not supported for now
         value[0] = 0;
         break;
-    case HWC_VSYNC_PERIOD:
+    case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1
         value[0] = m->fps;
         ALOGI("fps: %d", value[0]);
         break;
+    case HWC_DISPLAY_TYPES_SUPPORTED:
+        //Enable later
+        //if(ctx->mMDP.hasOverlay)
+            //supported |= HWC_DISPLAY_EXTERNAL_BIT;
+        value[0] = supported;
+        break;
     default:
         return -EINVAL;
     }
@@ -196,45 +222,122 @@
 
 }
 
+static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    if (LIKELY(list && list->numHwLayers)) {
+        VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY);
+        MDPComp::draw(ctx, list);
+        hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY);
+        //TODO We dont check for SKIP flag on this layer because we need PAN
+        //always. Last layer is always FB
+        uint32_t last = list->numHwLayers - 1;
+        if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET) {
+            ctx->mFbDev->post(ctx->mFbDev, list->hwLayers[last].handle);
+        }
+    }
+    return 0;
+}
+
+static int hwc_set_external(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    if (LIKELY(list && list->numHwLayers)) {
+        hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
+        uint32_t last = list->numHwLayers - 1;
+        if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET &&
+            ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
+            //ctx->mExtDisplay->post(list->hwLayers[last].handle);
+        }
+    }
+    return 0;
+}
+
 static int hwc_set(hwc_composer_device_1 *dev,
                    size_t numDisplays,
                    hwc_display_contents_1_t** displays)
 {
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    for (uint32_t i = 0; i <numDisplays; i++) {
+    for (uint32_t i = 0; i < numDisplays; i++) {
         hwc_display_contents_1_t* list = displays[i];
-        //XXX: Actually handle the multiple displays
-        if (LIKELY(list)) {
-            VideoOverlay::draw(ctx, list);
-            ExtOnly::draw(ctx, list);
-            MDPComp::draw(ctx, list);
-
-            //Sync TODO better error handling.
-            hwc_sync(list);
-
-            EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy,
-                                                (EGLSurface)list->sur);
-            wait4fbPost(ctx);
-            //Can draw to HDMI only when fb_post is reached
-            UIMirrorOverlay::draw(ctx);
-            //HDMI commit and primary commit (PAN) happening in parallel
-            if(ctx->mExtDisplay->getExternalDisplay())
-                ctx->mExtDisplay->commit();
-            //Virtual barrier for threads to finish
-            wait4Pan(ctx);
-        } else {
-            ctx->mOverlay->setState(ovutils::OV_CLOSED);
-            ctx->qbuf->unlockAll();
+        switch(i) {
+            case HWC_DISPLAY_PRIMARY:
+                ret = hwc_set_primary(ctx, list);
+            case HWC_DISPLAY_EXTERNAL:
+                ret = hwc_set_external(ctx, list);
+            default:
+                ret = -EINVAL;
         }
-
-        if(!ctx->overlayInUse)
-            ctx->mOverlay->setState(ovutils::OV_CLOSED);
     }
-    ctx->qbuf->unlockAllPrevious();
+    if(!ctx->overlayInUse)
+        ctx->mOverlay->setState(ovutils::OV_CLOSED);
+
     return ret;
 }
 
+int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
+        uint32_t* configs, size_t* numConfigs) {
+    int ret = 0;
+    //in 1.1 there is no way to choose a config, report as config id # 0
+    //This config is passed to getDisplayAttributes. Ignore for now.
+    if(*numConfigs == 1)
+        *configs = 0;
+    switch(disp) {
+        case HWC_DISPLAY_PRIMARY:
+            ret = 0;
+            break;
+        case HWC_DISPLAY_EXTERNAL:
+            //Hack until hotplug is supported.
+            //This makes framework ignore external display.
+            ret = -1;
+            break;
+    }
+    return ret;
+}
+
+int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
+        uint32_t config, const uint32_t* attributes, int32_t* values) {
+
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    //From HWComposer
+    static const uint32_t DISPLAY_ATTRIBUTES[] = {
+        HWC_DISPLAY_VSYNC_PERIOD,
+        HWC_DISPLAY_WIDTH,
+        HWC_DISPLAY_HEIGHT,
+        HWC_DISPLAY_DPI_X,
+        HWC_DISPLAY_DPI_Y,
+        HWC_DISPLAY_NO_ATTRIBUTE,
+    };
+
+    const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
+            sizeof(DISPLAY_ATTRIBUTES)[0]);
+
+    for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
+        switch (attributes[i]) {
+        case HWC_DISPLAY_VSYNC_PERIOD:
+            values[i] = ctx->dpyAttr[disp].vsync_period;
+            break;
+        case HWC_DISPLAY_WIDTH:
+            values[i] = ctx->dpyAttr[disp].xres;
+            ALOGD("%s width = %d",__FUNCTION__, ctx->dpyAttr[disp].xres);
+            break;
+        case HWC_DISPLAY_HEIGHT:
+            values[i] = ctx->dpyAttr[disp].yres;
+            ALOGD("%s height = %d",__FUNCTION__, ctx->dpyAttr[disp].yres);
+            break;
+        case HWC_DISPLAY_DPI_X:
+            values[i] = ctx->dpyAttr[disp].xdpi;
+            break;
+        case HWC_DISPLAY_DPI_Y:
+            values[i] = ctx->dpyAttr[disp].ydpi;
+            break;
+        default:
+            ALOGE("Unknown display attribute %d",
+                    attributes[i]);
+            return -EINVAL;
+        }
+    }
+    return 0;
+}
+
 static int hwc_device_close(struct hw_device_t *dev)
 {
     if(!dev) {
@@ -261,17 +364,20 @@
         initContext(dev);
 
         //Setup HWC methods
-        dev->device.common.tag     = HARDWARE_DEVICE_TAG;
-        dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
-        dev->device.common.module  = const_cast<hw_module_t*>(module);
-        dev->device.common.close   = hwc_device_close;
-        dev->device.prepare        = hwc_prepare;
-        dev->device.set            = hwc_set;
-        dev->device.eventControl   = hwc_eventControl;
-        dev->device.blank          = hwc_blank;
-        dev->device.query          = hwc_query;
-        dev->device.registerProcs  = hwc_registerProcs;
-        *device                    = &dev->device.common;
+        dev->device.common.tag          = HARDWARE_DEVICE_TAG;
+        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_1;
+        dev->device.common.module       = const_cast<hw_module_t*>(module);
+        dev->device.common.close        = hwc_device_close;
+        dev->device.prepare             = hwc_prepare;
+        dev->device.set                 = hwc_set;
+        dev->device.eventControl        = hwc_eventControl;
+        dev->device.blank               = hwc_blank;
+        dev->device.query               = hwc_query;
+        dev->device.registerProcs       = hwc_registerProcs;
+        dev->device.dump                = NULL;
+        dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
+        dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
+        *device = &dev->device.common;
         status = 0;
     }
     return status;
diff --git a/libhwcomposer/hwc_extonly.cpp b/libhwcomposer/hwc_extonly.cpp
index bc8bfe0..3be9d81 100644
--- a/libhwcomposer/hwc_extonly.cpp
+++ b/libhwcomposer/hwc_extonly.cpp
@@ -17,7 +17,6 @@
 
 #include "hwc_extonly.h"
 #include "external.h"
-#include "hwc_qbuf.h"
 
 namespace qhwc {
 
@@ -130,8 +129,6 @@
     private_handle_t *hnd = (private_handle_t *)
             list->hwLayers[sExtIndex].handle;
 
-    // Lock this buffer for read.
-    ctx->qbuf->lockAndAdd(hnd);
     bool ret = true;
     overlay::Overlay& ov = *(ctx->mOverlay);
     ovutils::eOverlayState state = ov.getState();
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 146b6f2..6d40741 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -17,7 +17,6 @@
  */
 
 #include "hwc_mdpcomp.h"
-#include "hwc_qbuf.h"
 #include "external.h"
 
 #define SUPPORT_4LAYER 0
@@ -332,23 +331,16 @@
  * 5. Overlay in use
  */
 
-bool MDPComp::is_doable(hwc_composer_device_1_t *dev,
-                        hwc_display_contents_1_t* list) {
-    hwc_context_t* ctx = (hwc_context_t*)(dev);
-
-    if(!ctx) {
-        ALOGE("%s: hwc context is NULL", __FUNCTION__);
-        return false;
-    }
-
+bool MDPComp::is_doable(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
     //Number of layers
-    if(list->numHwLayers < 1 || list->numHwLayers > (uint32_t)sMaxLayers) {
+    int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    if(numAppLayers < 1 || numAppLayers > (uint32_t)sMaxLayers) {
         ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
         return false;
     }
 
     //Disable MDPComp when ext display connected
-    if(ctx->mExtDisplay->getExternalDisplay()) {
+    if(isExternalActive(ctx)) {
         ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__);
         return false;
     }
@@ -360,7 +352,7 @@
     }
 
     //MDP composition is not efficient if rotation is needed.
-    for(unsigned int i = 0; i < list->numHwLayers; ++i) {
+    for(int i = 0; i < numAppLayers; ++i) {
         if(list->hwLayers[i].transform) {
                 ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
                 return false;
@@ -410,10 +402,11 @@
     }
 }
 
-int MDPComp::mark_layers(hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
-                                                    frame_info& current_frame) {
+int MDPComp::mark_layers(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
+        frame_info& current_frame) {
 
-    int layer_count = list->numHwLayers;
+    int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
 
     if(layer_count > sMaxLayers) {
         if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) {
@@ -476,10 +469,11 @@
     }
 }
 
-bool MDPComp::alloc_layer_pipes(hwc_display_contents_1_t* list,
-                        layer_mdp_info* layer_info, frame_info& current_frame) {
+bool MDPComp::alloc_layer_pipes(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list,
+        layer_mdp_info* layer_info, frame_info& current_frame) {
 
-    int layer_count = list->numHwLayers;
+    int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
     int mdp_count = current_frame.count;
     int fallback_count = layer_count - mdp_count;
     int frame_pipe_count = 0;
@@ -518,10 +512,10 @@
 }
 
 //returns array of layers and their allocated pipes
-bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* list,
-                                                  frame_info& current_frame ) {
+bool MDPComp::parse_and_allocate(hwc_context_t* ctx,
+        hwc_display_contents_1_t* list, frame_info& current_frame ) {
 
-    int layer_count = list->numHwLayers;
+    int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
 
     /* clear pipe status */
     sPipeMgr.reset();
@@ -532,7 +526,7 @@
     reset_layer_mdp_info(bp_layer_info, layer_count);
 
     /* iterate through layer list to mark candidate */
-    if(mark_layers(list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
+    if(mark_layers(ctx, list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
         free(bp_layer_info);
         current_frame.count = 0;
         ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
@@ -542,7 +536,7 @@
                           malloc(sizeof(pipe_layer_pair) * current_frame.count);
 
     /* allocate MDP pipes for marked layers */
-    alloc_layer_pipes( list, bp_layer_info, current_frame);
+    alloc_layer_pipes(ctx, list, bp_layer_info, current_frame);
 
     free(bp_layer_info);
     return true;
@@ -586,7 +580,7 @@
 
 bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
     int nPipeIndex, vsync_wait, isFG;
-    int numHwLayers = list->numHwLayers;
+    int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
 
     frame_info &current_frame = sCurrentFrame;
     current_frame.count = 0;
@@ -649,9 +643,6 @@
 
 void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
 {
-    if (!list)
-        return;
-
     for (int index = 0 ; index < sCurrentFrame.count; index++) {
         int l_index = sCurrentFrame.pipe_layer[index].layer_index;
         if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
@@ -678,7 +669,8 @@
 
     overlay::Overlay& ov = *(ctx->mOverlay);
 
-    for(unsigned int i = 0; i < list->numHwLayers; i++ )
+    int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    for(int i = 0; i < numHwLayers; i++ )
     {
         hwc_layer_1_t *layer = &list->hwLayers[i];
 
@@ -719,10 +711,6 @@
                 return -1;
             }
 
-            //lock buffer before queue
-            //XXX: Handle lock failure
-            ctx->qbuf->lockAndAdd(hnd);
-
             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
                                  using  pipe: %d", __FUNCTION__, layer,
                                  hnd, index );
@@ -793,17 +781,15 @@
     return true;
 }
 
-bool MDPComp::configure(hwc_composer_device_1_t *dev,  hwc_display_contents_1_t* list) {
+bool MDPComp::configure(hwc_context_t *ctx,  hwc_display_contents_1_t* list) {
 
     if(!isEnabled()) {
         ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
         return false;
     }
 
-    hwc_context_t* ctx = (hwc_context_t*)(dev);
-
     bool isMDPCompUsed = true;
-    bool doable = is_doable(dev, list);
+    bool doable = is_doable(ctx, list);
 
     if(doable) {
         if(setup(ctx, list)) {
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 53c85da..7fd6cee 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -154,7 +154,7 @@
     static bool deinit();
 
     /*sets up mdp comp for the current frame */
-    static bool configure(hwc_composer_device_1_t *ctx,  hwc_display_contents_1_t* list);
+    static bool configure(hwc_context_t *ctx,  hwc_display_contents_1_t* list);
 
     /* draw */
     static int draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
@@ -180,8 +180,7 @@
                         mdp_pipe_info& mdp_info);
 
     /* checks for conditions where mdpcomp is not possible */
-    static bool is_doable(hwc_composer_device_1_t *dev,
-                          hwc_display_contents_1_t* list);
+    static bool is_doable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
 
     static bool setup(hwc_context_t* ctx, hwc_display_contents_1_t* list);
 
@@ -189,8 +188,9 @@
     static void get_layer_info(hwc_layer_1_t* layer, int& flags);
 
     /* iterates through layer list to choose candidate to use overlay */
-    static int  mark_layers(hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
-                                                  frame_info& current_frame);
+    static int  mark_layers(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+            layer_mdp_info* layer_info, frame_info& current_frame);
+
     static bool parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* list,
                                                   frame_info& current_frame );
 
@@ -198,9 +198,10 @@
     static void reset_layer_mdp_info(layer_mdp_info* layer_mdp_info,int count);
 
     /* allocates pipes to selected candidates */
-    static bool alloc_layer_pipes(hwc_display_contents_1_t* list,
-                                  layer_mdp_info* layer_info,
-                                  frame_info& current_frame);
+    static bool alloc_layer_pipes(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list,
+            layer_mdp_info* layer_info,
+            frame_info& current_frame);
     /* updates variable pipe mode for the current frame */
     static int  configure_var_pipe(hwc_context_t* ctx);
 
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 3c1707b..3df0e25 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -38,26 +38,30 @@
     char* hdmi;
     int64_t timestamp = 0;
     const char *str = udata;
-    int hdmiconnected = ctx->mExtDisplay->getExternalDisplay();
+    int display = HWC_DISPLAY_PRIMARY;
 
     if(!strcasestr(str, "@/devices/virtual/graphics/fb")) {
         ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
         return;
     }
 
-    if(hdmiconnected)
+    //Check if its primary vsync
+    vsync = !strncmp(str, MSMFB_DEVICE_FB0, strlen(MSMFB_DEVICE_FB0));
+    //If not primary vsync, see if its an external vsync
+    if(isExternalActive(ctx) && !vsync) {
         vsync = !strncmp(str, MSMFB_DEVICE_FB1, strlen(MSMFB_DEVICE_FB1));
-    else
-        vsync = !strncmp(str, MSMFB_DEVICE_FB0, strlen(MSMFB_DEVICE_FB0));
+        display = HWC_DISPLAY_EXTERNAL;
+    }
 
     hdmi = strcasestr(str, MSMFB_HDMI_NODE);
+
     if(vsync) {
         str += strlen(str) + 1;
         while(*str) {
             if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
                 timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
                 //XXX: Handle vsync from multiple displays
-                ctx->proc->vsync(ctx->proc, (int)ctx->dpys[0], timestamp);
+                ctx->proc->vsync(ctx->proc, display, timestamp);
             }
             str += strlen(str) + 1;
             if(str - udata >= len)
diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp
index f904d69..1b81421 100644
--- a/libhwcomposer/hwc_uimirror.cpp
+++ b/libhwcomposer/hwc_uimirror.cpp
@@ -60,25 +60,25 @@
 }
 
 //Prepare the overlay for the UI mirroring
-bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
     sState = ovutils::OV_CLOSED;
     sIsUiMirroringOn = false;
 
     if(!ctx->mMDP.hasOverlay) {
-       ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring",
-                                                               __FUNCTION__);
+        ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring",
+                __FUNCTION__);
        return false;
     }
-    // If external display is connected
-    if(ctx->mExtDisplay->getExternalDisplay()) {
+    // If external display is active
+    if(isExternalActive(ctx)) {
         sState = ovutils::OV_UI_MIRROR;
-        configure(ctx, list);
+        configure(ctx, fblayer);
     }
     return sIsUiMirroringOn;
 }
 
 // Configure
-bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_display_contents_1_t *list)
+bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
 {
     if (LIKELY(ctx->mOverlay)) {
         overlay::Overlay& ov = *(ctx->mOverlay);
@@ -86,14 +86,8 @@
         ov.setState(sState);
         framebuffer_device_t *fbDev = ctx->mFbDev;
         if(fbDev) {
-            private_module_t* m = reinterpret_cast<private_module_t*>(
-                    fbDev->common.module);
-            int alignedW = ALIGN_TO(m->info.xres, 32);
-
-            private_handle_t const* hnd =
-                    reinterpret_cast<private_handle_t const*>(m->framebuffer);
-            unsigned int size = hnd->size/m->numBuffers;
-            ovutils::Whf info(alignedW, hnd->height, hnd->format, size);
+            private_handle_t *hnd = (private_handle_t *)layer->handle;
+            ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
             // Determine the RGB pipe for UI depending on the state
             ovutils::eDest dest = ovutils::OV_PIPE_ALL;
             if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) {
@@ -118,21 +112,26 @@
             ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
             ov.setSource(pargs, dest);
 
+            hwc_rect_t sourceCrop = layer->sourceCrop;
             // x,y,w,h
-            ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
+            ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
+                sourceCrop.right - sourceCrop.left,
+                sourceCrop.bottom - sourceCrop.top);
             ov.setCrop(dcrop, dest);
+
             //Get the current orientation on primary panel
             int transform = getDeviceOrientation();
             ovutils::eTransform orient =
                     static_cast<ovutils::eTransform>(transform);
             ov.setTransform(orient, dest);
 
-            ovutils::Dim dim;
-            dim.x = 0;
-            dim.y = 0;
-            dim.w = m->info.xres;
-            dim.h = m->info.yres;
-            ov.setPosition(dim, dest);
+            hwc_rect_t displayFrame = layer->displayFrame;
+            ovutils::Dim dpos(displayFrame.left,
+                displayFrame.top,
+                displayFrame.right - displayFrame.left,
+                displayFrame.bottom - displayFrame.top);
+            ov.setPosition(dpos, dest);
+
             if (!ov.commit(dest)) {
                 ALOGE("%s: commit fails", __FUNCTION__);
                 return false;
@@ -143,7 +142,7 @@
     return sIsUiMirroringOn;
 }
 
-bool UIMirrorOverlay::draw(hwc_context_t *ctx)
+bool UIMirrorOverlay::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
 {
     if(!sIsUiMirroringOn) {
         return true;
@@ -156,17 +155,21 @@
     if(fbDev) {
         private_module_t* m = reinterpret_cast<private_module_t*>(
                               fbDev->common.module);
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
         switch (state) {
             case ovutils::OV_UI_MIRROR:
-                if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset,
-                                                           ovutils::OV_PIPE0)) {
+                //TODO why is this primary fd
+                if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
+                            hnd->offset,  //div by line_length like in PAN?
+                            ovutils::OV_PIPE0)) {
                     ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
                     ret = false;
                 }
                 break;
             case ovutils::OV_2D_TRUE_UI_MIRROR:
-                if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset,
-                                                           ovutils::OV_PIPE2)) {
+                if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
+                            hnd->offset,
+                            ovutils::OV_PIPE2)) {
                     ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
                     ret = false;
                 }
diff --git a/libhwcomposer/hwc_uimirror.h b/libhwcomposer/hwc_uimirror.h
index a1bf9ba..c164d42 100644
--- a/libhwcomposer/hwc_uimirror.h
+++ b/libhwcomposer/hwc_uimirror.h
@@ -30,14 +30,14 @@
 class UIMirrorOverlay {
     public:
         // Sets up members and prepares overlay if conditions are met
-        static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+        static bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
         // Draws layer if this feature is on
-        static bool draw(hwc_context_t *ctx);
+        static bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
         //Reset values
         static void reset();
     private:
         //Configures overlay
-        static bool configure(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+        static bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
         //The chosen overlay state.
         static ovutils::eOverlayState sState;
         //Flags if this feature is on.
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index b957721..a4c7e3c 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -23,11 +23,8 @@
 #include "hwc_utils.h"
 #include "mdp_version.h"
 #include "hwc_video.h"
-#include "hwc_qbuf.h"
-#include "hwc_copybit.h"
 #include "external.h"
 #include "hwc_mdpcomp.h"
-#include "hwc_extonly.h"
 #include "QService.h"
 
 namespace qhwc {
@@ -38,6 +35,16 @@
     hw_module_t const *module;
     if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
         framebuffer_open(module, &(ctx->mFbDev));
+        private_module_t* m = reinterpret_cast<private_module_t*>(
+                ctx->mFbDev->common.module);
+        //xres, yres may not be 32 aligned
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = m->info.xres;
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = m->info.yres;
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = ctx->mFbDev->xdpi;
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ctx->mFbDev->ydpi;
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
+                1000000000l / ctx->mFbDev->fps;
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = openFb(HWC_DISPLAY_PRIMARY);
     }
 }
 
@@ -46,12 +53,10 @@
     openFramebufferDevice(ctx);
     ctx->mOverlay = overlay::Overlay::getInstance();
     ctx->mQService = qService::QService::getInstance(ctx);
-    ctx->qbuf = new QueuedBufferStore();
     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
     ctx->mExtDisplay = new ExternalDisplay(ctx);
-    memset(ctx->dpys,(int)EGL_NO_DISPLAY, MAX_NUM_DISPLAYS);
     MDPComp::init(ctx);
 
     ALOGI("Initializing Qualcomm Hardware Composer");
@@ -65,19 +70,11 @@
         ctx->mOverlay = NULL;
     }
 
-    if(ctx->mCopybitEngine) {
-        delete ctx->mCopybitEngine;
-        ctx->mCopybitEngine = NULL;
-    }
-
     if(ctx->mFbDev) {
         framebuffer_close(ctx->mFbDev);
         ctx->mFbDev = NULL;
-    }
-
-    if(ctx->qbuf) {
-        delete ctx->qbuf;
-        ctx->qbuf = NULL;
+        close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
     }
 
     if(ctx->mExtDisplay) {
@@ -101,56 +98,28 @@
           l->displayFrame.bottom);
 }
 
-void getLayerStats(hwc_context_t *ctx, const hwc_display_contents_1_t *list)
-{
-    //Video specific stats
-    int yuvCount = 0;
-    int yuvLayerIndex = -1;
-    bool isYuvLayerSkip = false;
-    int skipCount = 0;
-    int ccLayerIndex = -1; //closed caption
-    int extLayerIndex = -1; //ext-only or block except closed caption
-    int extCount = 0; //ext-only except closed caption
-    bool isExtBlockPresent = false; //is BLOCK layer present
-    bool yuvSecure = false;
+void setListStats(hwc_context_t *ctx,
+        const hwc_display_contents_1_t *list, int dpy) {
+
+    ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
+    ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
 
     for (size_t i = 0; i < list->numHwLayers; i++) {
         private_handle_t *hnd =
             (private_handle_t *)list->hwLayers[i].handle;
 
-        if (UNLIKELY(isYuvBuffer(hnd))) {
-            yuvCount++;
-            yuvLayerIndex = i;
-            yuvSecure = isSecureBuffer(hnd);
-            //Animating
-            //Do not mark as SKIP if it is secure buffer
-            if (isSkipLayer(&list->hwLayers[i]) && !yuvSecure) {
-                isYuvLayerSkip = true;
-                skipCount++;
-            }
-        } else if(UNLIKELY(isExtCC(hnd))) {
-            ccLayerIndex = i;
-        } else if(UNLIKELY(isExtBlock(hnd))) {
-            extCount++;
-            extLayerIndex = i;
-            isExtBlockPresent = true;
-        } else if(UNLIKELY(isExtOnly(hnd))) {
-            extCount++;
-            //If BLOCK layer present, dont cache index, display BLOCK only.
-            if(isExtBlockPresent == false) extLayerIndex = i;
+        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
+            continue;
+        //We disregard FB being skip for now! so the else if
         } else if (isSkipLayer(&list->hwLayers[i])) {
-            skipCount++;
+            ctx->listStats[dpy].skipCount++;
+        }
+
+        if (UNLIKELY(isYuvBuffer(hnd))) {
+            ctx->listStats[dpy].yuvCount++;
+            ctx->listStats[dpy].yuvIndex = i;
         }
     }
-
-    VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip,
-            ccLayerIndex);
-    ExtOnly::setStats(extCount, extLayerIndex, isExtBlockPresent);
-    CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
-    MDPComp::setStats(skipCount);
-
-    ctx->numHwLayers = list->numHwLayers;
-    return;
 }
 
 //Crops source buffer against destination and FB boundaries
@@ -209,41 +178,15 @@
     }
 }
 
-void wait4fbPost(hwc_context_t* ctx) {
-    framebuffer_device_t *fbDev = ctx->mFbDev;
-    if(fbDev) {
-        private_module_t* m = reinterpret_cast<private_module_t*>(
-                              fbDev->common.module);
-        //wait for the fb_post to be called
-        pthread_mutex_lock(&m->fbPostLock);
-        while(m->fbPostDone == false) {
-            pthread_cond_wait(&(m->fbPostCond), &(m->fbPostLock));
-        }
-        m->fbPostDone = false;
-        pthread_mutex_unlock(&m->fbPostLock);
-    }
+bool isExternalActive(hwc_context_t* ctx) {
+    return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
 }
 
-void wait4Pan(hwc_context_t* ctx) {
-    framebuffer_device_t *fbDev = ctx->mFbDev;
-    if(fbDev) {
-        private_module_t* m = reinterpret_cast<private_module_t*>(
-                              fbDev->common.module);
-        //wait for the fb_post's PAN to finish
-        pthread_mutex_lock(&m->fbPanLock);
-        while(m->fbPanDone == false) {
-            pthread_cond_wait(&(m->fbPanCond), &(m->fbPanLock));
-        }
-        m->fbPanDone = false;
-        pthread_mutex_unlock(&m->fbPanLock);
-    }
-}
-
-int hwc_sync(hwc_display_contents_1_t* list) {
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy) {
     int ret = 0;
 #ifdef USE_FENCE_SYNC
     struct mdp_buf_sync data;
-    int acquireFd[10];
+    int acquireFd[4];
     int count = 0;
     int releaseFd = -1;
     int fbFd = -1;
@@ -252,7 +195,8 @@
     data.rel_fen_fd = &releaseFd;
     //Accumulate acquireFenceFds
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
-        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+        if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
+            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) &&
             list->hwLayers[i].acquireFenceFd != -1) {
             acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
@@ -260,13 +204,7 @@
 
     if (count) {
         data.acq_fen_fd_cnt = count;
-
-        //Open fb0 for ioctl
-        fbFd = open("/dev/graphics/fb0", O_RDWR);
-        if (fbFd < 0) {
-            ALOGE("%s: /dev/graphics/fb0 not available", __FUNCTION__);
-            return -1;
-        }
+        fbFd = ctx->dpyAttr[dpy].fd;
 
         //Waits for acquire fences, returns a release fence
         ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
@@ -274,22 +212,20 @@
             ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
                     strerror(errno));
         }
-        close(fbFd);
 
         for(uint32_t i = 0; i < list->numHwLayers; i++) {
-            if(list->hwLayers[i].compositionType == HWC_OVERLAY) {
+            if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
+                list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)) {
                 //Close the acquireFenceFds
                 if(list->hwLayers[i].acquireFenceFd > 0) {
                     close(list->hwLayers[i].acquireFenceFd);
                     list->hwLayers[i].acquireFenceFd = -1;
                 }
                 //Populate releaseFenceFds.
-                if (releaseFd != -1)
-                    list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+                list->hwLayers[i].releaseFenceFd = dup(releaseFd);
             }
         }
-        if (releaseFd != -1)
-            close(releaseFd);
+        list->retireFenceFd = releaseFd;
     }
 #endif
     return ret;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 1153cc7..1b1d4d6 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -19,6 +19,7 @@
 #define HWC_UTILS_H
 
 #define HWC_REMOVE_DEPRECATED_VERSIONS 1
+#include <fcntl.h>
 #include <hardware/hwcomposer.h>
 #include <gralloc_priv.h>
 
@@ -44,7 +45,6 @@
 //fwrd decl
 class QueuedBufferStore;
 class ExternalDisplay;
-class CopybitEngine;
 
 struct MDPInfo {
     int version;
@@ -52,16 +52,23 @@
     bool hasOverlay;
 };
 
-enum external_display_type {
-    EXT_TYPE_NONE,
-    EXT_TYPE_HDMI,
-    EXT_TYPE_WIFI
+struct DisplayAttributes {
+    uint32_t vsync_period; //nanos
+    uint32_t xres;
+    uint32_t yres;
+    uint32_t xdpi;
+    uint32_t ydpi;
+    int fd;
+    bool isActive;
 };
-enum HWCCompositionType {
-    HWC_USE_GPU = HWC_FRAMEBUFFER, // This layer is to be handled by
-                                   //                 Surfaceflinger
-    HWC_USE_OVERLAY = HWC_OVERLAY, // This layer is to be handled by the overlay
-    HWC_USE_COPYBIT                // This layer is to be handled by copybit
+
+struct ListStats {
+    int numAppLayers; //Total - 1, excluding FB layer.
+    int skipCount;
+    int fbLayerIndex; //Always last for now. = numAppLayers
+    //Video specific
+    int yuvCount;
+    int yuvIndex;
 };
 
 enum {
@@ -74,21 +81,18 @@
 // -----------------------------------------------------------------------------
 // Utility functions - implemented in hwc_utils.cpp
 void dumpLayer(hwc_layer_1_t const* l);
-void getLayerStats(hwc_context_t *ctx, const hwc_display_contents_1_t *list);
+void setListStats(hwc_context_t *ctx, const hwc_display_contents_1_t *list,
+        int dpy);
 void initContext(hwc_context_t *ctx);
 void closeContext(hwc_context_t *ctx);
 //Crops source buffer against destination and FB boundaries
 void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
         const int fbWidth, const int fbHeight);
 
-// Waits for the fb_post to be called
-void wait4fbPost(hwc_context_t* ctx);
-
-// Waits for the fb_post to finish PAN (primary commit)
-void wait4Pan(hwc_context_t* ctx);
+bool isExternalActive(hwc_context_t* ctx);
 
 //Sync point impl.
-int hwc_sync(hwc_display_contents_1_t* list);
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy);
 
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
@@ -134,6 +138,16 @@
     width = displayFrame.right - displayFrame.left;
     height = displayFrame.bottom - displayFrame.top;
 }
+
+static inline int openFb(int dpy) {
+    int fd = -1;
+    const char *devtmpl = "/dev/graphics/fb%u";
+    char name[64] = {0};
+    snprintf(name, 64, devtmpl, dpy);
+    fd = open(name, O_RDWR);
+    return fd;
+}
+
 }; //qhwc namespace
 
 // -----------------------------------------------------------------------------
@@ -144,20 +158,13 @@
     const hwc_procs_t* proc;
     int numHwLayers;
     int overlayInUse;
-    hwc_display_t dpys[MAX_NUM_DISPLAYS];
 
     //Framebuffer device
     framebuffer_device_t *mFbDev;
 
-    //Copybit Engine
-    qhwc::CopybitEngine* mCopybitEngine;
-
     //Overlay object - NULL for non overlay devices
     overlay::Overlay *mOverlay;
 
-    //QueuedBufferStore to hold buffers for overlay
-    qhwc::QueuedBufferStore *qbuf;
-
     //QService object
     qService::QService *mQService;
 
@@ -166,7 +173,9 @@
 
     qhwc::MDPInfo mMDP;
 
-    bool isPoweredDown;
+    qhwc::DisplayAttributes dpyAttr[HWC_NUM_DISPLAY_TYPES];
+
+    qhwc::ListStats listStats[HWC_NUM_DISPLAY_TYPES];
 
     //Securing in progress indicator
     bool mSecuring;
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index daf3f80..3aa7e7a 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -17,9 +17,8 @@
 
 #define VIDEO_DEBUG 0
 #include <overlay.h>
-#include "hwc_qbuf.h"
 #include "hwc_video.h"
-#include "external.h"
+#include "hwc_utils.h"
 
 namespace qhwc {
 
@@ -27,88 +26,81 @@
 
 //Static Members
 ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
-int VideoOverlay::sYuvCount = 0;
-int VideoOverlay::sYuvLayerIndex = -1;
-bool VideoOverlay::sIsYuvLayerSkip = false;
-int VideoOverlay::sCCLayerIndex = -1;
 bool VideoOverlay::sIsModeOn = false;
 
 //Cache stats, figure out the state, config overlay
-bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
-    sIsModeOn = false;
+bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+        int dpy) {
+    int yuvIndex =  ctx->listStats[dpy].yuvIndex;
+
     if(!ctx->mMDP.hasOverlay) {
        ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
        return false;
     }
-    if(sYuvLayerIndex == -1) {
+    if(yuvIndex == -1) {
         return false;
     }
-    chooseState(ctx);
-    //if the state chosen above is CLOSED, skip this block.
-    if(sState != ovutils::OV_CLOSED) {
-        hwc_layer_1_t *yuvLayer = &list->hwLayers[sYuvLayerIndex];
-        hwc_layer_1_t *ccLayer = NULL;
-        if(sCCLayerIndex != -1)
-            ccLayer = &list->hwLayers[sCCLayerIndex];
 
-        if(configure(ctx, yuvLayer, ccLayer)) {
-            markFlags(yuvLayer, ccLayer);
-            sIsModeOn = true;
-        }
+    //index guaranteed to be not -1 at this point
+    hwc_layer_1_t *yuvLayer = &list->hwLayers[yuvIndex];
+    chooseState(ctx, dpy, yuvLayer);
+    if(configure(ctx, dpy, yuvLayer)) {
+        markFlags(yuvLayer);
+        sIsModeOn = true;
     }
 
-    ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d,"
-            "IsYuvLayerSkip = %d, ccLayerIndex = %d, IsModeOn = %d",
-            __FUNCTION__, sYuvCount, sYuvLayerIndex,
-            sIsYuvLayerSkip, sCCLayerIndex, sIsModeOn);
-
     return sIsModeOn;
 }
 
-void VideoOverlay::chooseState(hwc_context_t *ctx) {
+void VideoOverlay::chooseState(hwc_context_t *ctx, int dpy,
+        hwc_layer_1_t *yuvLayer) {
     ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
             ovutils::getStateString(sState));
 
-    ovutils::eOverlayState newState = ovutils::OV_CLOSED;
-
-    //Support 1 video layer
-    if(sYuvCount == 1) {
-        //Skip on primary, display on ext.
-        if(sIsYuvLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
-            newState = ovutils::OV_2D_VIDEO_ON_TV;
-        } else if(sIsYuvLayerSkip) { //skip on primary, no ext
-            newState = ovutils::OV_CLOSED;
-        } else if(ctx->mExtDisplay->getExternalDisplay()) {
-            //display on both
-            newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
-        } else { //display on primary only
-            newState = ovutils::OV_2D_VIDEO_ON_PANEL;
-        }
+    private_handle_t *hnd = NULL;
+    if(yuvLayer) {
+        hnd = (private_handle_t *)yuvLayer->handle;
     }
+    ovutils::eOverlayState newState = ovutils::OV_CLOSED;
+    switch(dpy) {
+        case HWC_DISPLAY_PRIMARY:
+            if(ctx->listStats[dpy].yuvCount == 1) {
+                newState = ovutils::OV_2D_VIDEO_ON_PANEL;
+                if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
+                    newState = ovutils::OV_CLOSED;
+                }
+            }
+            break;
+        case HWC_DISPLAY_EXTERNAL:
+        //TODO needs overlay state change for UI also
+            newState = sState; //Previously set by HWC_DISPLAY_PRIMARY
+            /*if(ctx->listStats[dpy].yuvCount == 1 && isExternalActive(ctx)) {
+                if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
+                    switch(sState) { //set by primary chooseState
+                        case ovutils::OV_2D_VIDEO_ON_PANEL:
+                            //upgrade
+                            sState = ovutils::OV_2D_VIDEO_PANEL_TV;
+                            break;
+                        case ovutils::OV_CLOSED:
+                            sState = ovutils::OV_2D_VIDEO_ON_TV;
+                            break;
+                    }
+                }
+            }*/
+            break;
+        default:
+            break;
+    }
+
     sState = newState;
     ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
             ovutils::getStateString(sState));
 }
 
-void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer, hwc_layer_1_t *ccLayer) {
-    switch(sState) {
-        case ovutils::OV_2D_VIDEO_ON_PANEL:
-        case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
-            if(yuvLayer) {
-                yuvLayer->compositionType = HWC_OVERLAY;
-                yuvLayer->hints |= HWC_HINT_CLEAR_FB;
-            }
-            if(ccLayer) {
-                ccLayer->compositionType = HWC_OVERLAY;
-            }
-            break;
-        case ovutils::OV_2D_VIDEO_ON_TV:
-            if(ccLayer) {
-                ccLayer->compositionType = HWC_OVERLAY;
-            }
-            break; //dont update video layer flags.
-        default:
-            break;
+void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
+    if(yuvLayer) {
+        yuvLayer->compositionType = HWC_OVERLAY;
+        yuvLayer->hints |= HWC_HINT_CLEAR_FB;
     }
 }
 
@@ -119,7 +111,7 @@
     ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
 
     ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
-    if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+    if (isSecureBuffer(hnd)) {
         ovutils::setMdpFlags(mdpFlags,
                 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
     }
@@ -161,7 +153,7 @@
     //Only for Primary
     ov.setCrop(dcrop, ovutils::OV_PIPE0);
 
-    int transform = layer->transform & FINAL_TRANSFORM_MASK;
+    int transform = layer->transform;
     ovutils::eTransform orient =
             static_cast<ovutils::eTransform>(transform);
     ov.setTransform(orient, ovutils::OV_PIPE0);
@@ -186,7 +178,7 @@
     ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
 
     ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
-    if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+    if (isSecureBuffer(hnd)) {
         ovutils::setMdpFlags(mdpFlags,
                 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
     }
@@ -233,144 +225,83 @@
     return true;
 }
 
-bool configExtCC(hwc_context_t *ctx, hwc_layer_1_t *layer) {
-    if(layer == NULL)
-        return true;
-
-    overlay::Overlay& ov = *(ctx->mOverlay);
-    private_handle_t *hnd = (private_handle_t *)layer->handle;
-    ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
-    ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
-    ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
-    ovutils::PipeArgs parg(mdpFlags,
-            info,
-            ovutils::ZORDER_1,
-            isFgFlag,
-            ovutils::ROT_FLAG_DISABLED);
-    ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
-    ov.setSource(pargs, ovutils::OV_PIPE2);
-
-    hwc_rect_t sourceCrop = layer->sourceCrop;
-    // x,y,w,h
-    ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
-            sourceCrop.right - sourceCrop.left,
-            sourceCrop.bottom - sourceCrop.top);
-    //Only for External
-    ov.setCrop(dcrop, ovutils::OV_PIPE2);
-
-    // FIXME: Use source orientation for TV when source is portrait
-    //Only for External
-    ov.setTransform(0, ovutils::OV_PIPE2);
-
-    //Setting position same as crop
-    //FIXME stretch to full screen
-    ov.setPosition(dcrop, ovutils::OV_PIPE2);
-
-    if (!ov.commit(ovutils::OV_PIPE2)) {
-        ALOGE("%s: commit fails", __FUNCTION__);
-        return false;
-    }
-    return true;
-}
-
-bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_1_t *yuvLayer,
-        hwc_layer_1_t *ccLayer) {
-
+bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
+        hwc_layer_1_t *yuvLayer) {
     bool ret = true;
-    if (LIKELY(ctx->mOverlay)) {
-        overlay::Overlay& ov = *(ctx->mOverlay);
-        // Set overlay state
-        ov.setState(sState);
-        switch(sState) {
-            case ovutils::OV_2D_VIDEO_ON_PANEL:
-                ret &= configPrimVid(ctx, yuvLayer);
-                break;
-            case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
-                ret &= configExtVid(ctx, yuvLayer);
-                ret &= configExtCC(ctx, ccLayer);
-                ret &= configPrimVid(ctx, yuvLayer);
-                break;
-            case ovutils::OV_2D_VIDEO_ON_TV:
-                ret &= configExtVid(ctx, yuvLayer);
-                ret &= configExtCC(ctx, ccLayer);
-                break;
-            default:
-                return false;
-        }
-    } else {
-        //Ov null
-        return false;
+    overlay::Overlay& ov = *(ctx->mOverlay);
+    switch(dpy) {
+        case HWC_DISPLAY_PRIMARY:
+            // Set overlay state
+            ov.setState(sState);
+            switch(sState) {
+                case ovutils::OV_2D_VIDEO_ON_PANEL:
+                    ret &= configPrimVid(ctx, yuvLayer);
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        case HWC_DISPLAY_EXTERNAL:
+            ov.setState(sState);
+            switch(sState) {
+                case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
+                case ovutils::OV_2D_VIDEO_ON_TV:
+                    ret = configExtVid(ctx, yuvLayer);
+                    break;
+                default:
+                    return false;
+            }
+            break;
     }
     return ret;
 }
 
-bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list)
+bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+        int dpy)
 {
-    if(!sIsModeOn || sYuvLayerIndex == -1) {
+    int yuvIndex = ctx->listStats[dpy].yuvIndex;
+    if(!sIsModeOn || yuvIndex == -1) {
         return true;
     }
 
     private_handle_t *hnd = (private_handle_t *)
-            list->hwLayers[sYuvLayerIndex].handle;
-
-    private_handle_t *cchnd = NULL;
-    if(sCCLayerIndex != -1) {
-        cchnd = (private_handle_t *)list->hwLayers[sCCLayerIndex].handle;
-        ctx->qbuf->lockAndAdd(cchnd);
-    }
-
-    // Lock this buffer for read.
-    ctx->qbuf->lockAndAdd(hnd);
+            list->hwLayers[yuvIndex].handle;
 
     bool ret = true;
     overlay::Overlay& ov = *(ctx->mOverlay);
     ovutils::eOverlayState state = ov.getState();
 
-    switch (state) {
-        case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
-            // Play external
-            if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
-                ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
-                ret = false;
-            }
-            //Play CC on external
-            if (cchnd && !ov.queueBuffer(cchnd->fd, cchnd->offset,
-                        ovutils::OV_PIPE2)) {
-                ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__);
-                ret = false;
-            }
-            // Play primary
-            if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
-                ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
-                ret = false;
+    switch(dpy) {
+        case HWC_DISPLAY_PRIMARY:
+            switch (state) {
+                case ovutils::OV_2D_VIDEO_ON_PANEL:
+                    // Play primary
+                    if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
+                        ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
+                        ret = false;
+                    }
+                    break;
+                default:
+                    ret = false;
+                    break;
             }
             break;
-        case ovutils::OV_2D_VIDEO_ON_PANEL:
-            // Play primary
-            if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
-                ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
-                ret = false;
+        case HWC_DISPLAY_EXTERNAL:
+            switch(state) {
+                case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
+                case ovutils::OV_2D_VIDEO_ON_TV:
+                    // Play external
+                    if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
+                        ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
+                        ret = false;
+                    }
+                    break;
+                default:
+                    ret = false;
+                    break;
             }
             break;
-        case ovutils::OV_2D_VIDEO_ON_TV:
-            // Play external
-            if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
-                ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
-                ret = false;
-            }
-            //Play CC on external
-            if (cchnd && !ov.queueBuffer(cchnd->fd, cchnd->offset,
-                        ovutils::OV_PIPE2)) {
-                ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__);
-                ret = false;
-            }
-            break;
-        default:
-            ALOGE("%s Unused state %s", __FUNCTION__,
-                    ovutils::getStateString(state));
-            break;
     }
-
     return ret;
 }
 
diff --git a/libhwcomposer/hwc_video.h b/libhwcomposer/hwc_video.h
index ec8fa21..f5a9709 100644
--- a/libhwcomposer/hwc_video.h
+++ b/libhwcomposer/hwc_video.h
@@ -26,53 +26,29 @@
 class VideoOverlay {
 public:
     //Sets up members and prepares overlay if conditions are met
-    static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+    static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+            int dpy);
     //Draws layer if this feature is on
-    static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-    //Receives data from hwc
-    static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip,
-            int ccLayerIndex);
+    static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+            int dpy);
     //resets values
     static void reset();
 private:
     //Choose an appropriate overlay state based on conditions
-    static void chooseState(hwc_context_t *ctx);
+    static void chooseState(hwc_context_t *ctx, int dpy,
+        hwc_layer_1_t *yuvLayer);
     //Configures overlay for video prim and ext
-    static bool configure(hwc_context_t *ctx, hwc_layer_1_t *yuvlayer,
-            hwc_layer_1_t *ccLayer);
+    static bool configure(hwc_context_t *ctx, int dpy,
+            hwc_layer_1_t *yuvlayer);
     //Marks layer flags if this feature is used
-    static void markFlags(hwc_layer_1_t *yuvLayer, hwc_layer_1_t *ccLayer);
-    //returns yuv count
-    static int getYuvCount();
-
+    static void markFlags(hwc_layer_1_t *yuvLayer);
     //The chosen overlay state.
     static ovutils::eOverlayState sState;
-    //Number of yuv layers in this drawing round
-    static int sYuvCount;
-    //Index of YUV layer, relevant only if count is 1
-    static int sYuvLayerIndex;
-    //Flags if a yuv layer is animating or below something that is animating
-    static bool sIsYuvLayerSkip;
-    //Holds the closed caption layer index, -1 by default
-    static int sCCLayerIndex;
     //Flags if this feature is on.
     static bool sIsModeOn;
 };
 
-inline void VideoOverlay::setStats(int yuvCount, int yuvLayerIndex,
-        bool isYuvLayerSkip, int ccLayerIndex) {
-    sYuvCount = yuvCount;
-    sYuvLayerIndex = yuvLayerIndex;
-    sIsYuvLayerSkip = isYuvLayerSkip;
-    sCCLayerIndex = ccLayerIndex;
-}
-
-inline int VideoOverlay::getYuvCount() { return sYuvCount; }
 inline void VideoOverlay::reset() {
-    sYuvCount = 0;
-    sYuvLayerIndex = -1;
-    sIsYuvLayerSkip = false;
-    sCCLayerIndex = -1;
     sIsModeOn = false;
     sState = ovutils::OV_CLOSED;
 }